fuzzgen: Generate call_indirect instructions (#6077)

* fuzzgen: Add `call_indirect`

* fuzzgen: Assign `call` results to variables
This commit is contained in:
Afonso Bordado
2023-03-22 11:24:53 +00:00
committed by GitHub
parent 3957d577b7
commit a1072007b8

View File

@@ -9,7 +9,7 @@ use cranelift::codegen::ir::stackslot::StackSize;
use cranelift::codegen::ir::{
types::*, AtomicRmwOp, Block, ConstantData, ExternalName, FuncRef, Function, LibCall, Opcode,
Signature, StackSlot, Type, UserExternalName, UserFuncName, Value,
SigRef, Signature, StackSlot, Type, UserExternalName, UserFuncName, Value,
};
use cranelift::codegen::isa::CallConv;
use cranelift::frontend::{FunctionBuilder, FunctionBuilderContext, Switch, Variable};
@@ -72,18 +72,33 @@ fn insert_call(
fgen: &mut FunctionGenerator,
builder: &mut FunctionBuilder,
opcode: Opcode,
_args: &[Type],
args: &[Type],
_rets: &[Type],
) -> Result<()> {
assert_eq!(opcode, Opcode::Call, "only call handled at the moment");
let (sig, func_ref) = fgen.u.choose(&fgen.resources.func_refs)?.clone();
assert!(matches!(opcode, Opcode::Call | Opcode::CallIndirect));
let (sig, sig_ref, func_ref) = fgen.u.choose(&fgen.resources.func_refs)?.clone();
let actuals = fgen.generate_values_for_signature(
builder,
sig.params.iter().map(|abi_param| abi_param.value_type),
)?;
builder.ins().call(func_ref, &actuals);
let call = if opcode == Opcode::Call {
builder.ins().call(func_ref, &actuals)
} else {
let addr_ty = args[0];
let addr = builder.ins().func_addr(addr_ty, func_ref);
builder.ins().call_indirect(sig_ref, addr, &actuals)
};
// Assign the return values to random variables
let ret_values = builder.inst_results(call).to_vec();
let ret_types = sig.returns.iter().map(|p| p.value_type);
for (ty, val) in ret_types.zip(ret_values) {
let var = fgen.get_variable_of_type(ty)?;
builder.def_var(var, val);
}
Ok(())
}
@@ -799,7 +814,7 @@ static OPCODE_SIGNATURES: Lazy<Vec<OpcodeSignature>> = Lazy::new(|| {
(Opcode::ResumableTrap),
(Opcode::Trapnz),
(Opcode::ResumableTrapnz),
(Opcode::CallIndirect),
(Opcode::CallIndirect, &[I32]),
(Opcode::ReturnCall),
(Opcode::ReturnCallIndirect),
(Opcode::FuncAddr),
@@ -1498,7 +1513,7 @@ struct Resources {
blocks: Vec<(Block, BlockSignature)>,
blocks_without_params: Vec<Block>,
block_terminators: Vec<BlockTerminator>,
func_refs: Vec<(Signature, FuncRef)>,
func_refs: Vec<(Signature, SigRef, FuncRef)>,
stack_slots: Vec<(StackSlot, StackSize)>,
usercalls: Vec<(UserExternalName, Signature)>,
libcalls: Vec<LibCall>,
@@ -1862,7 +1877,9 @@ where
colocated: self.u.arbitrary()?,
});
self.resources.func_refs.push((signature, func_ref));
self.resources
.func_refs
.push((signature, sig_ref, func_ref));
}
Ok(())