Add meta definition for bitcast.
This instruction uses two type variables: input and output. Make sure that our parser can handle it. The output type variable annotation is mandatory. Add a ValueTypeSet::example() method which is used to provide better diagnostics for a missing type variable.
This commit is contained in:
@@ -817,14 +817,7 @@ represented as a floating point number.
|
|||||||
Conversion operations
|
Conversion operations
|
||||||
---------------------
|
---------------------
|
||||||
|
|
||||||
.. inst:: a = bitcast x
|
.. autoinst:: bitcast
|
||||||
|
|
||||||
Reinterpret the bits in ``x`` as a different type.
|
|
||||||
|
|
||||||
The input and output types must be storable to memory and of the same size.
|
|
||||||
A bitcast is equivalent to storing one type and loading the other type from
|
|
||||||
the same address.
|
|
||||||
|
|
||||||
.. inst:: a = itrunc x
|
.. inst:: a = itrunc x
|
||||||
.. inst:: a = uext x
|
.. inst:: a = uext x
|
||||||
.. inst:: a = sext x
|
.. inst:: a = sext x
|
||||||
|
|||||||
@@ -761,4 +761,29 @@ nearest = Instruction(
|
|||||||
""",
|
""",
|
||||||
ins=x, outs=a)
|
ins=x, outs=a)
|
||||||
|
|
||||||
|
|
||||||
|
#
|
||||||
|
# Conversions
|
||||||
|
#
|
||||||
|
|
||||||
|
Mem = TypeVar(
|
||||||
|
'Mem', 'Any type that can be stored in memory',
|
||||||
|
ints=True, floats=True, simd=True)
|
||||||
|
MemTo = TypeVar(
|
||||||
|
'MemTo', 'Any type that can be stored in memory',
|
||||||
|
ints=True, floats=True, simd=True)
|
||||||
|
|
||||||
|
x = Operand('x', Mem)
|
||||||
|
a = Operand('a', MemTo, 'Bits of `x` reinterpreted')
|
||||||
|
|
||||||
|
bitcast = Instruction(
|
||||||
|
'bitcast', r"""
|
||||||
|
Reinterpret the bits in `x` as a different type.
|
||||||
|
|
||||||
|
The input and output types must be storable to memory and of the same
|
||||||
|
size. A bitcast is equivalent to storing one type and loading the other
|
||||||
|
type from the same address.
|
||||||
|
""",
|
||||||
|
ins=x, outs=a)
|
||||||
|
|
||||||
instructions.close()
|
instructions.close()
|
||||||
|
|||||||
@@ -432,6 +432,30 @@ impl ValueTypeSet {
|
|||||||
};
|
};
|
||||||
allowed && self.is_base_type(typ.lane_type())
|
allowed && self.is_base_type(typ.lane_type())
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Get an example member of this type set.
|
||||||
|
///
|
||||||
|
/// This is used for error messages to avoid suggesting invalid types.
|
||||||
|
pub fn example(&self) -> Type {
|
||||||
|
if self.base != types::VOID {
|
||||||
|
return self.base;
|
||||||
|
}
|
||||||
|
let t = if self.all_ints {
|
||||||
|
types::I32
|
||||||
|
} else if self.all_floats {
|
||||||
|
types::F32
|
||||||
|
} else if self.allow_scalars {
|
||||||
|
types::B1
|
||||||
|
} else {
|
||||||
|
types::B32
|
||||||
|
};
|
||||||
|
|
||||||
|
if self.allow_scalars {
|
||||||
|
t
|
||||||
|
} else {
|
||||||
|
t.by(4).unwrap()
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Operand constraints. This describes the value type constraints on a single `Value` operand.
|
/// Operand constraints. This describes the value type constraints on a single `Value` operand.
|
||||||
@@ -506,4 +530,49 @@ mod tests {
|
|||||||
// that?
|
// that?
|
||||||
assert_eq!(mem::size_of::<InstructionData>(), 16);
|
assert_eq!(mem::size_of::<InstructionData>(), 16);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn value_set() {
|
||||||
|
use types::*;
|
||||||
|
|
||||||
|
let vts = ValueTypeSet {
|
||||||
|
allow_scalars: true,
|
||||||
|
allow_simd: true,
|
||||||
|
base: VOID,
|
||||||
|
all_ints: true,
|
||||||
|
all_floats: false,
|
||||||
|
all_bools: true,
|
||||||
|
};
|
||||||
|
assert_eq!(vts.example().to_string(), "i32");
|
||||||
|
|
||||||
|
let vts = ValueTypeSet {
|
||||||
|
allow_scalars: true,
|
||||||
|
allow_simd: true,
|
||||||
|
base: VOID,
|
||||||
|
all_ints: false,
|
||||||
|
all_floats: true,
|
||||||
|
all_bools: true,
|
||||||
|
};
|
||||||
|
assert_eq!(vts.example().to_string(), "f32");
|
||||||
|
|
||||||
|
let vts = ValueTypeSet {
|
||||||
|
allow_scalars: false,
|
||||||
|
allow_simd: true,
|
||||||
|
base: VOID,
|
||||||
|
all_ints: false,
|
||||||
|
all_floats: true,
|
||||||
|
all_bools: true,
|
||||||
|
};
|
||||||
|
assert_eq!(vts.example().to_string(), "f32x4");
|
||||||
|
|
||||||
|
let vts = ValueTypeSet {
|
||||||
|
allow_scalars: false,
|
||||||
|
allow_simd: true,
|
||||||
|
base: VOID,
|
||||||
|
all_ints: false,
|
||||||
|
all_floats: false,
|
||||||
|
all_bools: true,
|
||||||
|
};
|
||||||
|
assert_eq!(vts.example().to_string(), "b32x4");
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -651,7 +651,10 @@ impl<'a> Parser<'a> {
|
|||||||
} else if constraints.is_polymorphic() {
|
} else if constraints.is_polymorphic() {
|
||||||
// This opcode does not support type inference, so the explicit type variable
|
// This opcode does not support type inference, so the explicit type variable
|
||||||
// is required.
|
// is required.
|
||||||
return err!(self.loc, "type variable required for polymorphic opcode");
|
return err!(self.loc,
|
||||||
|
"type variable required for polymorphic opcode, e.g. '{}.{}'",
|
||||||
|
opcode,
|
||||||
|
constraints.ctrl_typeset().unwrap().example());
|
||||||
} else {
|
} else {
|
||||||
// This is a non-polymorphic opcode. No typevar needed.
|
// This is a non-polymorphic opcode. No typevar needed.
|
||||||
VOID
|
VOID
|
||||||
|
|||||||
@@ -42,3 +42,11 @@ ebb0(vx0: f32, vx1: f32):
|
|||||||
v1 = fcmp uno, vx0, vx1
|
v1 = fcmp uno, vx0, vx1
|
||||||
v2 = fcmp lt, vx0, vx1
|
v2 = fcmp lt, vx0, vx1
|
||||||
}
|
}
|
||||||
|
|
||||||
|
; The bitcast instruction has two type variables: The controlling type variable
|
||||||
|
; controls the outout type, and the input type is a free variable.
|
||||||
|
function bitcast(i32, f32) {
|
||||||
|
ebb0(vx0: i32, vx1: f32):
|
||||||
|
v0 = bitcast.i8x4 vx0
|
||||||
|
v1 = bitcast.i32 vx1
|
||||||
|
}
|
||||||
|
|||||||
@@ -35,3 +35,9 @@ ebb0(vx0: f32, vx1: f32):
|
|||||||
v1 = fcmp uno, vx0, vx1
|
v1 = fcmp uno, vx0, vx1
|
||||||
v2 = fcmp lt, vx0, vx1
|
v2 = fcmp lt, vx0, vx1
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function bitcast(i32, f32) {
|
||||||
|
ebb0(vx0: i32, vx1: f32):
|
||||||
|
v0 = bitcast.i8x4 vx0
|
||||||
|
v1 = bitcast.i32 vx1
|
||||||
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user