Add reference types R32 and R64

-Add resumable_trap, safepoint, isnull, and null instructions
-Add Stackmap struct and StackmapSink trait

Co-authored-by: Mir Ahmed <mirahmed753@gmail.com>
Co-authored-by: Dan Gohman <sunfish@mozilla.com>
This commit is contained in:
Carmen Kwan
2019-07-23 16:28:54 -07:00
committed by Dan Gohman
parent b659262d2a
commit 19257f80c1
47 changed files with 1027 additions and 62 deletions

View File

@@ -12,7 +12,7 @@ use crate::cdsl::formats::{
};
use crate::cdsl::operands::Operand;
use crate::cdsl::type_inference::Constraint;
use crate::cdsl::types::{LaneType, ValueType, VectorType};
use crate::cdsl::types::{LaneType, ReferenceType, ValueType, VectorType};
use crate::cdsl::typevar::TypeVar;
#[derive(Copy, Clone, PartialEq, Eq, Hash, PartialOrd, Ord)]
@@ -177,6 +177,10 @@ impl Instruction {
bind(self.clone(), Some(lane_type.into()), Vec::new())
}
pub fn bind_ref(&self, reference_type: impl Into<ReferenceType>) -> BoundInstruction {
bind_ref(self.clone(), Some(reference_type.into()), Vec::new())
}
pub fn bind_vector(&self, lane_type: impl Into<LaneType>, num_lanes: u64) -> BoundInstruction {
bind_vector(self.clone(), lane_type.into(), num_lanes, Vec::new())
}
@@ -406,6 +410,10 @@ impl BoundInstruction {
bind(self.inst, Some(lane_type.into()), self.value_types)
}
pub fn bind_ref(self, reference_type: impl Into<ReferenceType>) -> BoundInstruction {
bind_ref(self.inst, Some(reference_type.into()), self.value_types)
}
pub fn bind_vector(self, lane_type: impl Into<LaneType>, num_lanes: u64) -> BoundInstruction {
bind_vector(self.inst, lane_type.into(), num_lanes, self.value_types)
}
@@ -1043,6 +1051,13 @@ impl InstSpec {
InstSpec::Bound(inst) => inst.clone().bind(lane_type),
}
}
pub fn bind_ref(&self, reference_type: impl Into<ReferenceType>) -> BoundInstruction {
match self {
InstSpec::Inst(inst) => inst.bind_ref(reference_type),
InstSpec::Bound(inst) => inst.clone().bind_ref(reference_type),
}
}
}
impl Into<InstSpec> for &Instruction {
@@ -1077,6 +1092,26 @@ fn bind(
BoundInstruction { inst, value_types }
}
/// Helper bind for reference types reused by {Bound,}Instruction::bind_ref.
fn bind_ref(
inst: Instruction,
reference_type: Option<ReferenceType>,
mut value_types: Vec<ValueTypeOrAny>,
) -> BoundInstruction {
match reference_type {
Some(reference_type) => {
value_types.push(ValueTypeOrAny::ValueType(reference_type.into()));
}
None => {
value_types.push(ValueTypeOrAny::Any);
}
}
verify_polymorphic_binding(&inst, &value_types);
BoundInstruction { inst, value_types }
}
/// Helper bind for vector types reused by {Bound,}Instruction::bind.
fn bind_vector(
inst: Instruction,

View File

@@ -11,12 +11,14 @@ use crate::shared::types as shared_types;
//
// 0: Void
// 0x01-0x6f: Special types
// 0x70-0x7f: Lane types
// 0x70-0x7d: Lane types
// 0x7e-0x7f: Reference types
// 0x80-0xff: Vector types
//
// Vector types are encoded with the lane type in the low 4 bits and log2(lanes)
// in the high 4 bits, giving a range of 2-256 lanes.
static LANE_BASE: u8 = 0x70;
static REFERENCE_BASE: u8 = 0x7E;
// Rust name prefix used for the `rust_name` method.
static _RUST_NAME_PREFIX: &'static str = "ir::types::";
@@ -31,6 +33,7 @@ static _RUST_NAME_PREFIX: &'static str = "ir::types::";
pub enum ValueType {
BV(BVType),
Lane(LaneType),
Reference(ReferenceType),
Special(SpecialType),
Vector(VectorType),
}
@@ -46,11 +49,16 @@ impl ValueType {
SpecialTypeIterator::new()
}
pub fn all_reference_types() -> ReferenceTypeIterator {
ReferenceTypeIterator::new()
}
/// Return a string containing the documentation comment for this type.
pub fn doc(&self) -> String {
match *self {
ValueType::BV(ref b) => b.doc(),
ValueType::Lane(l) => l.doc(),
ValueType::Reference(r) => r.doc(),
ValueType::Special(s) => s.doc(),
ValueType::Vector(ref v) => v.doc(),
}
@@ -61,6 +69,7 @@ impl ValueType {
match *self {
ValueType::BV(ref b) => b.lane_bits(),
ValueType::Lane(l) => l.lane_bits(),
ValueType::Reference(r) => r.lane_bits(),
ValueType::Special(s) => s.lane_bits(),
ValueType::Vector(ref v) => v.lane_bits(),
}
@@ -84,6 +93,7 @@ impl ValueType {
match *self {
ValueType::BV(_) => None,
ValueType::Lane(l) => Some(l.number()),
ValueType::Reference(r) => Some(r.number()),
ValueType::Special(s) => Some(s.number()),
ValueType::Vector(ref v) => Some(v.number()),
}
@@ -112,6 +122,7 @@ impl fmt::Display for ValueType {
match *self {
ValueType::BV(ref b) => b.fmt(f),
ValueType::Lane(l) => l.fmt(f),
ValueType::Reference(r) => r.fmt(f),
ValueType::Special(s) => s.fmt(f),
ValueType::Vector(ref v) => v.fmt(f),
}
@@ -132,6 +143,13 @@ impl From<LaneType> for ValueType {
}
}
/// Create a ValueType from a given reference type.
impl From<ReferenceType> for ValueType {
fn from(reference: ReferenceType) -> Self {
ValueType::Reference(reference)
}
}
/// Create a ValueType from a given special type.
impl From<SpecialType> for ValueType {
fn from(spec: SpecialType) -> Self {
@@ -515,3 +533,83 @@ impl Iterator for SpecialTypeIterator {
}
}
}
/// Reference type is scalar type, but not lane type.
#[derive(Clone, Copy, PartialEq, Eq, Hash)]
pub struct ReferenceType(pub shared_types::Reference);
impl ReferenceType {
/// Return a string containing the documentation comment for this reference type.
pub fn doc(self) -> String {
format!("An opaque reference type with {} bits.", self.lane_bits())
}
/// Return the number of bits in a lane.
pub fn lane_bits(self) -> u64 {
match self.0 {
shared_types::Reference::R32 => 32,
shared_types::Reference::R64 => 64,
}
}
/// Find the unique number associated with this reference type.
pub fn number(self) -> u8 {
REFERENCE_BASE
+ match self {
ReferenceType(shared_types::Reference::R32) => 0,
ReferenceType(shared_types::Reference::R64) => 1,
}
}
pub fn ref_from_bits(num_bits: u16) -> ReferenceType {
ReferenceType(match num_bits {
32 => shared_types::Reference::R32,
64 => shared_types::Reference::R64,
_ => unreachable!("unexpected number of bits for a reference type"),
})
}
}
impl fmt::Display for ReferenceType {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
write!(f, "r{}", self.lane_bits())
}
}
impl fmt::Debug for ReferenceType {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
write!(f, "ReferenceType(bits={})", self.lane_bits())
}
}
/// Create a ReferenceType from a given reference variant.
impl From<shared_types::Reference> for ReferenceType {
fn from(r: shared_types::Reference) -> Self {
ReferenceType(r)
}
}
/// An iterator for different reference types.
pub struct ReferenceTypeIterator {
reference_iter: shared_types::ReferenceIterator,
}
impl ReferenceTypeIterator {
/// Create a new reference type iterator.
fn new() -> Self {
Self {
reference_iter: shared_types::ReferenceIterator::new(),
}
}
}
impl Iterator for ReferenceTypeIterator {
type Item = ReferenceType;
fn next(&mut self) -> Option<Self::Item> {
if let Some(r) = self.reference_iter.next() {
Some(ReferenceType::from(r))
} else {
None
}
}
}

View File

@@ -6,7 +6,7 @@ use std::iter::FromIterator;
use std::ops;
use std::rc::Rc;
use crate::cdsl::types::{BVType, LaneType, SpecialType, ValueType};
use crate::cdsl::types::{BVType, LaneType, ReferenceType, SpecialType, ValueType};
const MAX_LANES: u16 = 256;
const MAX_BITS: u16 = 64;
@@ -64,6 +64,10 @@ impl TypeVar {
ValueType::Special(special_type) => {
return TypeVar::new(name, doc, builder.specials(vec![special_type]).build());
}
ValueType::Reference(ReferenceType(reference_type)) => {
let bits = reference_type as RangeBound;
return TypeVar::new(name, doc, builder.refs(bits..bits).build());
}
ValueType::Lane(lane_type) => (lane_type, 1),
ValueType::Vector(vec_type) => {
(vec_type.lane_type(), vec_type.lane_count() as RangeBound)
@@ -406,6 +410,7 @@ pub struct TypeSet {
pub ints: NumSet,
pub floats: NumSet,
pub bools: NumSet,
pub refs: NumSet,
pub bitvecs: NumSet,
pub specials: Vec<SpecialType>,
}
@@ -416,6 +421,7 @@ impl TypeSet {
ints: NumSet,
floats: NumSet,
bools: NumSet,
refs: NumSet,
bitvecs: NumSet,
specials: Vec<SpecialType>,
) -> Self {
@@ -424,6 +430,7 @@ impl TypeSet {
ints,
floats,
bools,
refs,
bitvecs,
specials,
}
@@ -432,7 +439,11 @@ impl TypeSet {
/// Return the number of concrete types represented by this typeset.
pub fn size(&self) -> usize {
self.lanes.len()
* (self.ints.len() + self.floats.len() + self.bools.len() + self.bitvecs.len())
* (self.ints.len()
+ self.floats.len()
+ self.bools.len()
+ self.refs.len()
+ self.bitvecs.len())
+ self.specials.len()
}
@@ -462,6 +473,7 @@ impl TypeSet {
let mut copy = self.clone();
copy.ints = NumSet::new();
copy.floats = NumSet::new();
copy.refs = NumSet::new();
copy.bitvecs = NumSet::new();
if (&self.lanes - &num_set![1]).len() > 0 {
copy.bools = &self.ints | &self.floats;
@@ -544,6 +556,7 @@ impl TypeSet {
copy.ints = NumSet::new();
copy.bools = NumSet::new();
copy.floats = NumSet::new();
copy.refs = NumSet::new();
copy.bitvecs = self
.lanes
.iter()
@@ -568,6 +581,9 @@ impl TypeSet {
for &bits in &self.bools {
ret.push(LaneType::bool_from_bits(bits).by(num_lanes));
}
for &bits in &self.refs {
ret.push(ReferenceType::ref_from_bits(bits).into());
}
for &bits in &self.bitvecs {
assert_eq!(num_lanes, 1);
ret.push(BVType::new(bits).into());
@@ -630,6 +646,7 @@ impl TypeSet {
let mut ints = range_to_set(Some(8..MAX_BITS));
let mut floats = range_to_set(Some(32..64));
let mut bools = range_to_set(Some(1..MAX_BITS));
let refs = range_to_set(Some(32..64));
for &l in &all_lanes {
for &i in &all_ints {
@@ -654,7 +671,7 @@ impl TypeSet {
let bitvecs = NumSet::new();
let specials = Vec::new();
TypeSet::new(lanes, ints, floats, bools, bitvecs, specials)
TypeSet::new(lanes, ints, floats, bools, refs, bitvecs, specials)
}
}
}
@@ -664,6 +681,7 @@ impl TypeSet {
self.ints = &self.ints & &other.ints;
self.floats = &self.floats & &other.floats;
self.bools = &self.bools & &other.bools;
self.refs = &self.refs & &other.refs;
self.bitvecs = &self.bitvecs & &other.bitvecs;
let mut new_specials = Vec::new();
@@ -680,6 +698,7 @@ impl TypeSet {
&& self.ints.is_subset(&other.ints)
&& self.floats.is_subset(&other.floats)
&& self.bools.is_subset(&other.bools)
&& self.refs.is_subset(&other.refs)
&& self.bitvecs.is_subset(&other.bitvecs)
&& {
let specials: HashSet<SpecialType> = HashSet::from_iter(self.specials.clone());
@@ -692,12 +711,14 @@ impl TypeSet {
set_wider_or_equal(&self.ints, &other.ints)
&& set_wider_or_equal(&self.floats, &other.floats)
&& set_wider_or_equal(&self.bools, &other.bools)
&& set_wider_or_equal(&self.refs, &other.refs)
}
pub fn is_narrower(&self, other: &TypeSet) -> bool {
set_narrower(&self.ints, &other.ints)
&& set_narrower(&self.floats, &other.floats)
&& set_narrower(&self.bools, &other.bools)
&& set_narrower(&self.refs, &other.refs)
}
}
@@ -738,6 +759,12 @@ impl fmt::Debug for TypeSet {
Vec::from_iter(self.bools.iter().map(|x| x.to_string())).join(", ")
));
}
if !self.refs.is_empty() {
subsets.push(format!(
"refs={{{}}}",
Vec::from_iter(self.refs.iter().map(|x| x.to_string())).join(", ")
));
}
if !self.bitvecs.is_empty() {
subsets.push(format!(
"bitvecs={{{}}}",
@@ -760,6 +787,7 @@ pub struct TypeSetBuilder {
ints: Interval,
floats: Interval,
bools: Interval,
refs: Interval,
bitvecs: Interval,
includes_scalars: bool,
simd_lanes: Interval,
@@ -772,6 +800,7 @@ impl TypeSetBuilder {
ints: Interval::None,
floats: Interval::None,
bools: Interval::None,
refs: Interval::None,
bitvecs: Interval::None,
includes_scalars: true,
simd_lanes: Interval::None,
@@ -794,6 +823,11 @@ impl TypeSetBuilder {
self.bools = interval.into();
self
}
pub fn refs(mut self, interval: impl Into<Interval>) -> Self {
assert!(self.refs == Interval::None);
self.refs = interval.into();
self
}
pub fn includes_scalars(mut self, includes_scalars: bool) -> Self {
self.includes_scalars = includes_scalars;
self
@@ -827,6 +861,7 @@ impl TypeSetBuilder {
range_to_set(self.ints.to_range(8..MAX_BITS, None)),
range_to_set(self.floats.to_range(32..64, None)),
bools,
range_to_set(self.refs.to_range(32..64, None)),
range_to_set(self.bitvecs.to_range(1..MAX_BITVEC, None)),
self.specials,
)
@@ -837,6 +872,7 @@ impl TypeSetBuilder {
.ints(Interval::All)
.floats(Interval::All)
.bools(Interval::All)
.refs(Interval::All)
.simd_lanes(Interval::All)
.bitvecs(Interval::All)
.specials(ValueType::all_special_types().collect())