Fix Invalid Instruction format in fuzzgen (#4738)
* cranelift: Add assert to prevent wrong InstFormat being used for the wrong opcode * cranelift: Use correct instruction format when inserting opcodes in fuzzgen (fixes #4733) * cranelift: Use debug assert on InstFormat assert
This commit is contained in:
@@ -902,6 +902,9 @@ fn gen_format_constructor(format: &InstructionFormat, fmt: &mut Formatter) {
|
|||||||
fmtln!(fmt, "data.sign_extend_immediates(ctrl_typevar);");
|
fmtln!(fmt, "data.sign_extend_immediates(ctrl_typevar);");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Assert that this opcode belongs to this format
|
||||||
|
fmtln!(fmt, "debug_assert_eq!(opcode.format(), InstructionFormat::from(&data), \"Wrong InstructionFormat for Opcode: {}\", opcode);");
|
||||||
|
|
||||||
fmt.line("self.build(data, ctrl_typevar)");
|
fmt.line("self.build(data, ctrl_typevar)");
|
||||||
});
|
});
|
||||||
fmtln!(fmt, "}");
|
fmtln!(fmt, "}");
|
||||||
|
|||||||
@@ -4,6 +4,7 @@
|
|||||||
//! function. Many of its methods are generated from the meta language instruction definitions.
|
//! function. Many of its methods are generated from the meta language instruction definitions.
|
||||||
|
|
||||||
use crate::ir;
|
use crate::ir;
|
||||||
|
use crate::ir::instructions::InstructionFormat;
|
||||||
use crate::ir::types;
|
use crate::ir::types;
|
||||||
use crate::ir::{DataFlowGraph, InstructionData};
|
use crate::ir::{DataFlowGraph, InstructionData};
|
||||||
use crate::ir::{Inst, Opcode, Type, Value};
|
use crate::ir::{Inst, Opcode, Type, Value};
|
||||||
@@ -217,7 +218,7 @@ mod tests {
|
|||||||
use crate::cursor::{Cursor, FuncCursor};
|
use crate::cursor::{Cursor, FuncCursor};
|
||||||
use crate::ir::condcodes::*;
|
use crate::ir::condcodes::*;
|
||||||
use crate::ir::types::*;
|
use crate::ir::types::*;
|
||||||
use crate::ir::{Function, InstBuilder, ValueDef};
|
use crate::ir::{Function, InstBuilder, Opcode, TrapCode, ValueDef};
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn types() {
|
fn types() {
|
||||||
@@ -262,4 +263,17 @@ mod tests {
|
|||||||
assert!(iadd != iconst);
|
assert!(iadd != iconst);
|
||||||
assert_eq!(pos.func.dfg.value_def(v0), ValueDef::Result(iconst, 0));
|
assert_eq!(pos.func.dfg.value_def(v0), ValueDef::Result(iconst, 0));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
#[should_panic]
|
||||||
|
fn panics_when_inserting_wrong_opcode() {
|
||||||
|
let mut func = Function::new();
|
||||||
|
let block0 = func.dfg.make_block();
|
||||||
|
let mut pos = FuncCursor::new(&mut func);
|
||||||
|
pos.insert_block(block0);
|
||||||
|
|
||||||
|
// We are trying to create a Opcode::Return with the InstData::Trap, which is obviously wrong
|
||||||
|
pos.ins()
|
||||||
|
.Trap(Opcode::Return, I32, TrapCode::BadConversionToInteger);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,7 +1,8 @@
|
|||||||
use crate::codegen::ir::{ArgumentExtension, ArgumentPurpose, ValueList};
|
use crate::codegen::ir::{ArgumentExtension, ArgumentPurpose};
|
||||||
use crate::config::Config;
|
use crate::config::Config;
|
||||||
use anyhow::Result;
|
use anyhow::Result;
|
||||||
use arbitrary::{Arbitrary, Unstructured};
|
use arbitrary::{Arbitrary, Unstructured};
|
||||||
|
use cranelift::codegen::ir::instructions::InstructionFormat;
|
||||||
use cranelift::codegen::ir::{types::*, FuncRef, LibCall, UserExternalName, UserFuncName};
|
use cranelift::codegen::ir::{types::*, FuncRef, LibCall, UserExternalName, UserFuncName};
|
||||||
use cranelift::codegen::ir::{
|
use cranelift::codegen::ir::{
|
||||||
AbiParam, Block, ExternalName, Function, JumpTable, Opcode, Signature, StackSlot, Type, Value,
|
AbiParam, Block, ExternalName, Function, JumpTable, Opcode, Signature, StackSlot, Type, Value,
|
||||||
@@ -24,11 +25,11 @@ fn insert_opcode(
|
|||||||
args: &'static [Type],
|
args: &'static [Type],
|
||||||
rets: &'static [Type],
|
rets: &'static [Type],
|
||||||
) -> Result<()> {
|
) -> Result<()> {
|
||||||
let mut arg_vals = ValueList::new();
|
let mut vals = Vec::with_capacity(args.len());
|
||||||
for &arg in args.into_iter() {
|
for &arg in args.into_iter() {
|
||||||
let var = fgen.get_variable_of_type(arg)?;
|
let var = fgen.get_variable_of_type(arg)?;
|
||||||
let val = builder.use_var(var);
|
let val = builder.use_var(var);
|
||||||
arg_vals.push(val, &mut builder.func.dfg.value_lists);
|
vals.push(val);
|
||||||
}
|
}
|
||||||
|
|
||||||
// For pretty much every instruction the control type is the return type
|
// For pretty much every instruction the control type is the return type
|
||||||
@@ -42,7 +43,16 @@ fn insert_opcode(
|
|||||||
.copied()
|
.copied()
|
||||||
.unwrap_or(INVALID);
|
.unwrap_or(INVALID);
|
||||||
|
|
||||||
let (inst, dfg) = builder.ins().MultiAry(opcode, ctrl_type, arg_vals);
|
// Choose the appropriate instruction format for this opcode
|
||||||
|
let (inst, dfg) = match opcode.format() {
|
||||||
|
InstructionFormat::NullAry => builder.ins().NullAry(opcode, ctrl_type),
|
||||||
|
InstructionFormat::Unary => builder.ins().Unary(opcode, ctrl_type, vals[0]),
|
||||||
|
InstructionFormat::Binary => builder.ins().Binary(opcode, ctrl_type, vals[0], vals[1]),
|
||||||
|
InstructionFormat::Ternary => builder
|
||||||
|
.ins()
|
||||||
|
.Ternary(opcode, ctrl_type, vals[0], vals[1], vals[2]),
|
||||||
|
_ => unimplemented!(),
|
||||||
|
};
|
||||||
let results = dfg.inst_results(inst).to_vec();
|
let results = dfg.inst_results(inst).to_vec();
|
||||||
|
|
||||||
for (val, &ty) in results.into_iter().zip(rets) {
|
for (val, &ty) in results.into_iter().zip(rets) {
|
||||||
|
|||||||
Reference in New Issue
Block a user