@@ -574,6 +574,7 @@ void TranslateToFuzzReader::setupHeapTypes() {
574574 break ;
575575 case HeapTypeKind::Cont:
576576 interestingHeapSubTypes[cont].push_back (type);
577+ sigConts[type.getContinuation ().type ].push_back (type);
577578 break ;
578579 case HeapTypeKind::Basic:
579580 WASM_UNREACHABLE (" unexpected kind" );
@@ -5458,20 +5459,93 @@ Expression* TranslateToFuzzReader::makeBrOn(Type type) {
54585459}
54595460
54605461Expression* TranslateToFuzzReader::makeContBind (Type type) {
5461- auto sig = type.getHeapType ().getContinuation ().type .getSignature ();
5462- // Add a single param to be bound. TODO: Add multiple, and look in
5463- // interestingHeapTypes.
5464- std::vector<Type> newParams;
5465- for (auto t : sig.params ) {
5466- newParams.push_back (t);
5467- }
5468- auto newParam = getSingleConcreteType ();
5469- newParams.insert (newParams.begin (), newParam);
5470- auto newSig = Signature (Type (newParams), sig.results );
5471- auto newCont = Continuation (newSig);
5472- auto newType = Type (newCont, NonNullable, Exact);
5473- std::vector<Expression*> newArgs{make (newParam)};
5474- return builder.makeContBind (type.getHeapType (), newArgs, make (newType));
5462+ // We must output a signature that corresponds to the type we were given.
5463+ auto outputSigType = type.getHeapType ().getContinuation ().type ;
5464+ auto outputSig = outputSigType.getSignature ();
5465+ auto numOutputParams = outputSig.params .size ();
5466+
5467+ // Look for a compatible signature. Don't always do this, however - we have a
5468+ // few other options below.
5469+ std::optional<HeapType> inputSigType;
5470+ if (!oneIn (4 )) {
5471+ auto & funcTypes = interestingHeapSubTypes[HeapTypes::func];
5472+ // Filter out incompatible signatures.
5473+ std::vector<HeapType> relevantFuncTypes;
5474+ for (auto funcType : funcTypes) {
5475+ auto funcSig = funcType.getSignature ();
5476+ if (funcSig.results != outputSig.results ) {
5477+ // The results must match.
5478+ continue ;
5479+ }
5480+
5481+ // The params must be compatible. For example, with output params [x,y,z]
5482+ // we'd want an input signature like [a,b,x,y,z] so that we can bind a and
5483+ // b.
5484+ auto numInputParams = funcSig.params .size ();
5485+ if (numInputParams < numOutputParams) {
5486+ // Too short.
5487+ continue ;
5488+ }
5489+ // Ignoring the input params at the start, compare the tails.
5490+ auto numAddedParams = numInputParams - numOutputParams;
5491+ bool bad = false ;
5492+ for (Index i = 0 ; i < numOutputParams; i++) {
5493+ if (!Type::isSubType (outputSig.params [i],
5494+ funcSig.params [numAddedParams + i])) {
5495+ bad = true ;
5496+ break ;
5497+ }
5498+ }
5499+ if (!bad) {
5500+ relevantFuncTypes.push_back (funcType);
5501+ }
5502+ }
5503+ if (!relevantFuncTypes.empty ()) {
5504+ inputSigType = pick (relevantFuncTypes);
5505+ }
5506+ }
5507+
5508+ Index numAddedParams;
5509+ if (inputSigType) {
5510+ // We picked a signature, above.
5511+ numAddedParams =
5512+ inputSigType->getSignature ().params .size () - numOutputParams;
5513+ } else {
5514+ // We failed to find a signature, either use the current one (binding no
5515+ // input params) or invent a input one, adding one param.
5516+ if (oneIn (2 )) {
5517+ inputSigType = outputSigType;
5518+ numAddedParams = 0 ;
5519+ } else {
5520+ std::vector<Type> inputParams;
5521+ for (auto t : outputSig.params ) {
5522+ inputParams.push_back (t);
5523+ }
5524+ auto inputParam = getSingleConcreteType ();
5525+ inputParams.insert (inputParams.begin (), inputParam);
5526+ inputSigType = Signature (Type (inputParams), outputSig.results );
5527+ numAddedParams = 1 ;
5528+ }
5529+ }
5530+ auto inputSig = inputSigType->getSignature ();
5531+
5532+ // Pick a continuation type for the signature. If existing continuations use
5533+ // it, usually pick one of them.
5534+ auto & inputSigConts = sigConts[*inputSigType];
5535+ HeapType inputCont;
5536+ if (!inputSigConts.empty () && !oneIn (5 )) {
5537+ inputCont = pick (inputSigConts);
5538+ } else {
5539+ inputCont = Continuation (inputSig);
5540+ }
5541+ Type inputType = Type (inputCont, NonNullable, Exact);
5542+
5543+ // Generate the new args and the cont.bind.
5544+ std::vector<Expression*> newArgs;
5545+ for (Index i = 0 ; i < numAddedParams; i++) {
5546+ newArgs.push_back (make (inputSig.params [i]));
5547+ }
5548+ return builder.makeContBind (type.getHeapType (), newArgs, make (inputType));
54755549}
54765550
54775551bool TranslateToFuzzReader::maybeSignedGet (const Field& field) {
0 commit comments