Avoid dangling references to block params when sealing an unreachable block.
This commit is contained in:
@@ -429,24 +429,22 @@ iconst = Instruction(
|
|||||||
ins=N, outs=a)
|
ins=N, outs=a)
|
||||||
|
|
||||||
N = Operand('N', ieee32)
|
N = Operand('N', ieee32)
|
||||||
a = Operand('a', f32, doc='A constant integer scalar or vector value')
|
a = Operand('a', f32, doc='A constant f32 scalar value')
|
||||||
f32const = Instruction(
|
f32const = Instruction(
|
||||||
'f32const', r"""
|
'f32const', r"""
|
||||||
Floating point constant.
|
Floating point constant.
|
||||||
|
|
||||||
Create a :type:`f32` SSA value with an immediate constant value, or a
|
Create a :type:`f32` SSA value with an immediate constant value.
|
||||||
floating point vector where all the lanes have the same value.
|
|
||||||
""",
|
""",
|
||||||
ins=N, outs=a)
|
ins=N, outs=a)
|
||||||
|
|
||||||
N = Operand('N', ieee64)
|
N = Operand('N', ieee64)
|
||||||
a = Operand('a', f64, doc='A constant integer scalar or vector value')
|
a = Operand('a', f64, doc='A constant f64 scalar value')
|
||||||
f64const = Instruction(
|
f64const = Instruction(
|
||||||
'f64const', r"""
|
'f64const', r"""
|
||||||
Floating point constant.
|
Floating point constant.
|
||||||
|
|
||||||
Create a :type:`f64` SSA value with an immediate constant value, or a
|
Create a :type:`f64` SSA value with an immediate constant value.
|
||||||
floating point vector where all the lanes have the same value.
|
|
||||||
""",
|
""",
|
||||||
ins=N, outs=a)
|
ins=N, outs=a)
|
||||||
|
|
||||||
|
|||||||
@@ -199,6 +199,35 @@ enum Call {
|
|||||||
FinishPredecessorsLookup(Value, Ebb),
|
FinishPredecessorsLookup(Value, Ebb),
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Emit instructions to produce a zero value in the given type.
|
||||||
|
fn emit_zero(ty: Type, mut cur: FuncCursor) -> Value {
|
||||||
|
if ty.is_int() {
|
||||||
|
cur.ins().iconst(ty, 0)
|
||||||
|
} else if ty.is_bool() {
|
||||||
|
cur.ins().bconst(ty, false)
|
||||||
|
} else if ty == F32 {
|
||||||
|
cur.ins().f32const(Ieee32::with_bits(0))
|
||||||
|
} else if ty == F64 {
|
||||||
|
cur.ins().f64const(Ieee64::with_bits(0))
|
||||||
|
} else if ty.is_vector() {
|
||||||
|
let scalar_ty = ty.lane_type();
|
||||||
|
if scalar_ty.is_int() {
|
||||||
|
cur.ins().iconst(ty, 0)
|
||||||
|
} else if scalar_ty.is_bool() {
|
||||||
|
cur.ins().bconst(ty, false)
|
||||||
|
} else if scalar_ty == F32 {
|
||||||
|
let scalar = cur.ins().f32const(Ieee32::with_bits(0));
|
||||||
|
cur.ins().splat(ty, scalar)
|
||||||
|
} else if scalar_ty == F64 {
|
||||||
|
let scalar = cur.ins().f64const(Ieee64::with_bits(0));
|
||||||
|
cur.ins().splat(ty, scalar)
|
||||||
|
} else {
|
||||||
|
panic!("unimplemented scalar type: {:?}", ty)
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
panic!("unimplemented type: {:?}", ty)
|
||||||
|
}
|
||||||
|
}
|
||||||
/// The following methods are the API of the SSA builder. Here is how it should be used when
|
/// The following methods are the API of the SSA builder. Here is how it should be used when
|
||||||
/// translating to Cretonne IL:
|
/// translating to Cretonne IL:
|
||||||
///
|
///
|
||||||
@@ -484,30 +513,17 @@ where
|
|||||||
// The variable is used but never defined before. This is an irregularity in the
|
// The variable is used but never defined before. This is an irregularity in the
|
||||||
// code, but rather than throwing an error we silently initialize the variable to
|
// code, but rather than throwing an error we silently initialize the variable to
|
||||||
// 0. This will have no effect since this situation happens in unreachable code.
|
// 0. This will have no effect since this situation happens in unreachable code.
|
||||||
func.dfg.remove_ebb_param(temp_arg_val);
|
|
||||||
if !func.layout.is_ebb_inserted(dest_ebb) {
|
if !func.layout.is_ebb_inserted(dest_ebb) {
|
||||||
func.layout.append_ebb(dest_ebb)
|
func.layout.append_ebb(dest_ebb)
|
||||||
};
|
};
|
||||||
self.side_effects.instructions_added_to_ebbs.push(dest_ebb);
|
self.side_effects.instructions_added_to_ebbs.push(dest_ebb);
|
||||||
fn emit_zero(ty: Type, mut cur: FuncCursor) -> Value {
|
let zero = emit_zero(
|
||||||
if ty.is_int() {
|
|
||||||
cur.ins().iconst(ty, 0)
|
|
||||||
} else if ty.is_bool() {
|
|
||||||
cur.ins().bconst(ty, false)
|
|
||||||
} else if ty == F32 {
|
|
||||||
cur.ins().f32const(Ieee32::with_bits(0))
|
|
||||||
} else if ty == F64 {
|
|
||||||
cur.ins().f64const(Ieee64::with_bits(0))
|
|
||||||
} else if ty.is_vector() {
|
|
||||||
emit_zero(ty.lane_type(), cur)
|
|
||||||
} else {
|
|
||||||
panic!("use of undefined value unsupported for type {}", ty)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
emit_zero(
|
|
||||||
func.dfg.value_type(temp_arg_val),
|
func.dfg.value_type(temp_arg_val),
|
||||||
FuncCursor::new(func).at_first_insertion_point(dest_ebb),
|
FuncCursor::new(func).at_first_insertion_point(dest_ebb),
|
||||||
)
|
);
|
||||||
|
func.dfg.remove_ebb_param(temp_arg_val);
|
||||||
|
func.dfg.change_to_alias(temp_arg_val, zero);
|
||||||
|
zero
|
||||||
}
|
}
|
||||||
ZeroOneOrMore::One(pred_val) => {
|
ZeroOneOrMore::One(pred_val) => {
|
||||||
// Here all the predecessors use a single value to represent our variable
|
// Here all the predecessors use a single value to represent our variable
|
||||||
@@ -1130,4 +1146,37 @@ mod tests {
|
|||||||
Opcode::Iconst
|
Opcode::Iconst
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn unreachable_use() {
|
||||||
|
let mut func = Function::new();
|
||||||
|
let mut ssa: SSABuilder<Variable> = SSABuilder::new();
|
||||||
|
let ebb0 = func.dfg.make_ebb();
|
||||||
|
let ebb1 = func.dfg.make_ebb();
|
||||||
|
// Here is the pseudo-program we want to translate:
|
||||||
|
// ebb0:
|
||||||
|
// return
|
||||||
|
// ebb1:
|
||||||
|
// brz v1, ebb1
|
||||||
|
// jump ebb1
|
||||||
|
let _block0 = ssa.declare_ebb_header_block(ebb0);
|
||||||
|
ssa.seal_ebb_header_block(ebb0, &mut func);
|
||||||
|
let block1 = ssa.declare_ebb_header_block(ebb1);
|
||||||
|
let block2 = ssa.declare_ebb_body_block(block1);
|
||||||
|
{
|
||||||
|
let mut cur = FuncCursor::new(&mut func);
|
||||||
|
cur.insert_ebb(ebb0);
|
||||||
|
cur.insert_ebb(ebb1);
|
||||||
|
cur.goto_bottom(ebb0);
|
||||||
|
cur.ins().return_(&[]);
|
||||||
|
let x_var = Variable(0);
|
||||||
|
cur.goto_bottom(ebb1);
|
||||||
|
let val = ssa.use_var(&mut cur.func, x_var, I32, block1).0;
|
||||||
|
let brz = cur.ins().brz(val, ebb1, &[]);
|
||||||
|
ssa.declare_ebb_predecessor(ebb1, block1, brz);
|
||||||
|
let j = cur.ins().jump(ebb1, &[]);
|
||||||
|
ssa.declare_ebb_predecessor(ebb1, block2, j);
|
||||||
|
}
|
||||||
|
ssa.seal_ebb_header_block(ebb1, &mut func);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user