fuzzgen: Generate call_indirect instructions (#6077)
* fuzzgen: Add `call_indirect` * fuzzgen: Assign `call` results to variables
This commit is contained in:
@@ -9,7 +9,7 @@ use cranelift::codegen::ir::stackslot::StackSize;
|
|||||||
|
|
||||||
use cranelift::codegen::ir::{
|
use cranelift::codegen::ir::{
|
||||||
types::*, AtomicRmwOp, Block, ConstantData, ExternalName, FuncRef, Function, LibCall, Opcode,
|
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::codegen::isa::CallConv;
|
||||||
use cranelift::frontend::{FunctionBuilder, FunctionBuilderContext, Switch, Variable};
|
use cranelift::frontend::{FunctionBuilder, FunctionBuilderContext, Switch, Variable};
|
||||||
@@ -72,18 +72,33 @@ fn insert_call(
|
|||||||
fgen: &mut FunctionGenerator,
|
fgen: &mut FunctionGenerator,
|
||||||
builder: &mut FunctionBuilder,
|
builder: &mut FunctionBuilder,
|
||||||
opcode: Opcode,
|
opcode: Opcode,
|
||||||
_args: &[Type],
|
args: &[Type],
|
||||||
_rets: &[Type],
|
_rets: &[Type],
|
||||||
) -> Result<()> {
|
) -> Result<()> {
|
||||||
assert_eq!(opcode, Opcode::Call, "only call handled at the moment");
|
assert!(matches!(opcode, Opcode::Call | Opcode::CallIndirect));
|
||||||
let (sig, func_ref) = fgen.u.choose(&fgen.resources.func_refs)?.clone();
|
let (sig, sig_ref, func_ref) = fgen.u.choose(&fgen.resources.func_refs)?.clone();
|
||||||
|
|
||||||
let actuals = fgen.generate_values_for_signature(
|
let actuals = fgen.generate_values_for_signature(
|
||||||
builder,
|
builder,
|
||||||
sig.params.iter().map(|abi_param| abi_param.value_type),
|
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(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -799,7 +814,7 @@ static OPCODE_SIGNATURES: Lazy<Vec<OpcodeSignature>> = Lazy::new(|| {
|
|||||||
(Opcode::ResumableTrap),
|
(Opcode::ResumableTrap),
|
||||||
(Opcode::Trapnz),
|
(Opcode::Trapnz),
|
||||||
(Opcode::ResumableTrapnz),
|
(Opcode::ResumableTrapnz),
|
||||||
(Opcode::CallIndirect),
|
(Opcode::CallIndirect, &[I32]),
|
||||||
(Opcode::ReturnCall),
|
(Opcode::ReturnCall),
|
||||||
(Opcode::ReturnCallIndirect),
|
(Opcode::ReturnCallIndirect),
|
||||||
(Opcode::FuncAddr),
|
(Opcode::FuncAddr),
|
||||||
@@ -1498,7 +1513,7 @@ struct Resources {
|
|||||||
blocks: Vec<(Block, BlockSignature)>,
|
blocks: Vec<(Block, BlockSignature)>,
|
||||||
blocks_without_params: Vec<Block>,
|
blocks_without_params: Vec<Block>,
|
||||||
block_terminators: Vec<BlockTerminator>,
|
block_terminators: Vec<BlockTerminator>,
|
||||||
func_refs: Vec<(Signature, FuncRef)>,
|
func_refs: Vec<(Signature, SigRef, FuncRef)>,
|
||||||
stack_slots: Vec<(StackSlot, StackSize)>,
|
stack_slots: Vec<(StackSlot, StackSize)>,
|
||||||
usercalls: Vec<(UserExternalName, Signature)>,
|
usercalls: Vec<(UserExternalName, Signature)>,
|
||||||
libcalls: Vec<LibCall>,
|
libcalls: Vec<LibCall>,
|
||||||
@@ -1862,7 +1877,9 @@ where
|
|||||||
colocated: self.u.arbitrary()?,
|
colocated: self.u.arbitrary()?,
|
||||||
});
|
});
|
||||||
|
|
||||||
self.resources.func_refs.push((signature, func_ref));
|
self.resources
|
||||||
|
.func_refs
|
||||||
|
.push((signature, sig_ref, func_ref));
|
||||||
}
|
}
|
||||||
|
|
||||||
Ok(())
|
Ok(())
|
||||||
|
|||||||
Reference in New Issue
Block a user