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

@@ -85,6 +85,12 @@ pub fn define(
TypeSetBuilder::new().ints(32..64).build(),
);
let Ref = &TypeVar::new(
"Ref",
"A scalar reference type",
TypeSetBuilder::new().refs(Interval::All).build(),
);
let Testable = &TypeVar::new(
"Testable",
"A scalar boolean or integer type",
@@ -118,11 +124,12 @@ pub fn define(
let Any = &TypeVar::new(
"Any",
"Any integer, float, or boolean scalar or vector type",
"Any integer, float, boolean, or reference scalar or vector type",
TypeSetBuilder::new()
.ints(Interval::All)
.floats(Interval::All)
.bools(Interval::All)
.refs(Interval::All)
.simd_lanes(Interval::All)
.includes_scalars(true)
.build(),
@@ -394,6 +401,19 @@ pub fn define(
.can_trap(true),
);
ig.push(
Inst::new(
"resumable_trap",
r#"
A resumable trap.
This instruction allows non-conditional traps to be used as non-terminal instructions.
"#,
)
.operands_in(vec![code])
.can_trap(true),
);
ig.push(
Inst::new(
"trapnz",
@@ -1068,6 +1088,20 @@ pub fn define(
.operands_out(vec![a]),
);
let a = &operand_doc("a", Ref, "A constant reference null value");
ig.push(
Inst::new(
"null",
r#"
Null constant value for reference types.
Create a scalar reference SSA value with a constant null value.
"#,
)
.operands_out(vec![a]),
);
ig.push(Inst::new(
"nop",
r#"
@@ -1315,6 +1349,24 @@ pub fn define(
.other_side_effects(true),
);
let N = &operand_doc(
"args",
variable_args,
"Variable number of args for Stackmap",
);
ig.push(
Inst::new(
"safepoint",
r#"
This instruction will provide live reference values at a point in
the function. It can only be used by the compiler.
"#,
)
.operands_in(vec![N])
.other_side_effects(true),
);
let x = &operand_doc("x", TxN, "Vector to split");
let lo = &operand_doc("lo", &TxN.half_vector(), "Low-numbered lanes of `x`");
let hi = &operand_doc("hi", &TxN.half_vector(), "High-numbered lanes of `x`");
@@ -2578,6 +2630,23 @@ pub fn define(
.operands_out(vec![a]),
);
let a = &operand("a", b1);
let x = &operand("x", Ref);
ig.push(
Inst::new(
"is_null",
r#"
Reference verification.
The condition code determines if the reference type in question is
null or not.
"#,
)
.operands_in(vec![x])
.operands_out(vec![a]),
);
let Cond = &operand("Cond", intcc);
let f = &operand("f", iflags);
let a = &operand("a", b1);

View File

@@ -92,6 +92,18 @@ pub fn define() -> SettingGroup {
true,
);
settings.add_bool(
"enable_safepoints",
r#"
Enable safepoint instruction insertions.
This will allow the emit_stackmaps() function to insert the safepoint
instruction on top of calls and interrupt traps in order to display the
live reference values at that point in the program.
"#,
false,
);
// Settings specific to the `baldrdash` calling convention.
settings.add_enum(

View File

@@ -145,6 +145,38 @@ impl Iterator for FlagIterator {
}
}
#[derive(Debug, Clone, Copy, Eq, PartialEq, Hash)]
pub enum Reference {
/// 32-bit reference.
R32 = 32,
/// 64-bit reference.
R64 = 64,
}
/// This provides an iterator through all of the supported reference variants.
pub struct ReferenceIterator {
index: u8,
}
impl ReferenceIterator {
pub fn new() -> Self {
Self { index: 0 }
}
}
impl Iterator for ReferenceIterator {
type Item = Reference;
fn next(&mut self) -> Option<Self::Item> {
let res = match self.index {
0 => Some(Reference::R32),
1 => Some(Reference::R64),
_ => return None,
};
self.index += 1;
res
}
}
#[cfg(test)]
mod iter_tests {
use super::*;
@@ -185,4 +217,12 @@ mod iter_tests {
assert_eq!(flag_iter.next(), Some(Flag::FFlags));
assert_eq!(flag_iter.next(), None);
}
#[test]
fn reference_iter_works() {
let mut reference_iter = ReferenceIterator::new();
assert_eq!(reference_iter.next(), Some(Reference::R32));
assert_eq!(reference_iter.next(), Some(Reference::R64));
assert_eq!(reference_iter.next(), None);
}
}