diff options
Diffstat (limited to 'src/tools/fuzzing.h')
-rw-r--r-- | src/tools/fuzzing.h | 166 |
1 files changed, 69 insertions, 97 deletions
diff --git a/src/tools/fuzzing.h b/src/tools/fuzzing.h index fb83882c2..f4188eb08 100644 --- a/src/tools/fuzzing.h +++ b/src/tools/fuzzing.h @@ -845,6 +845,11 @@ private: return std::string("label$") + std::to_string(labelIndex++); } + // Weighting for the core make* methods. Some nodes are important enough that + // we should do them quite often. + static const size_t VeryImportant = 4; + static const size_t Important = 2; + // always call the toplevel make(type) command, not the internal specific ones int nesting = 0; @@ -884,57 +889,37 @@ private: nesting--; return ret; } + Expression* _makeConcrete(Type type) { bool canMakeControlFlow = !type.isMulti() || wasm.features.has(FeatureSet::Multivalue); - auto choice = upTo(100); - if (choice < 10) { - return makeConst(type); - } - if (choice < 30) { - return makeLocalSet(type); - } - if (choice < 50) { - return makeLocalGet(type); - } - if (choice < 60 && canMakeControlFlow) { - return makeBlock(type); - } - if (choice < 70 && canMakeControlFlow) { - return makeIf(type); - } - if (choice < 80 && canMakeControlFlow) { - return makeLoop(type); - } - if (choice < 90 && canMakeControlFlow) { - return makeBreak(type); - } using Self = TranslateToFuzzReader; FeatureOptions<Expression* (Self::*)(Type)> options; + using WeightedOption = decltype(options)::WeightedOption; options.add(FeatureSet::MVP, - &Self::makeLocalGet, - &Self::makeLocalSet, - &Self::makeGlobalGet, - &Self::makeConst); + WeightedOption{&Self::makeLocalGet, VeryImportant}, + WeightedOption{&Self::makeLocalSet, VeryImportant}, + WeightedOption{&Self::makeGlobalGet, Important}, + WeightedOption{&Self::makeConst, Important}); if (canMakeControlFlow) { options.add(FeatureSet::MVP, - &Self::makeBlock, - &Self::makeIf, - &Self::makeLoop, - &Self::makeBreak, + WeightedOption{&Self::makeBlock, Important}, + WeightedOption{&Self::makeIf, Important}, + WeightedOption{&Self::makeLoop, Important}, + WeightedOption{&Self::makeBreak, Important}, &Self::makeCall, &Self::makeCallIndirect); } if (type.isSingle()) { options .add(FeatureSet::MVP, - &Self::makeUnary, - &Self::makeBinary, + WeightedOption{&Self::makeUnary, Important}, + WeightedOption{&Self::makeBinary, Important}, &Self::makeSelect) .add(FeatureSet::Multivalue, &Self::makeTupleExtract); } if (type.isSingle() && !type.isRef()) { - options.add(FeatureSet::MVP, &Self::makeLoad); + options.add(FeatureSet::MVP, {&Self::makeLoad, Important}); options.add(FeatureSet::SIMD, &Self::makeSIMD); } if (type.isInteger()) { @@ -958,75 +943,48 @@ private: return makeMemoryHashLogging(); } } - choice = upTo(100); - if (choice < 50) { - return makeLocalSet(Type::none); - } - if (choice < 60) { - return makeBlock(Type::none); - } - if (choice < 70) { - return makeIf(Type::none); - } - if (choice < 80) { - return makeLoop(Type::none); - } - if (choice < 90) { - return makeBreak(Type::none); - } using Self = TranslateToFuzzReader; - auto options = FeatureOptions<Expression* (Self::*)(Type)>() - .add(FeatureSet::MVP, - &Self::makeBlock, - &Self::makeIf, - &Self::makeLoop, - &Self::makeBreak, - &Self::makeCall, - &Self::makeCallIndirect, - &Self::makeLocalSet, - &Self::makeStore, - &Self::makeDrop, - &Self::makeNop, - &Self::makeGlobalSet) - .add(FeatureSet::BulkMemory, &Self::makeBulkMemory) - .add(FeatureSet::Atomics, &Self::makeAtomic); + auto options = FeatureOptions<Expression* (Self::*)(Type)>(); + using WeightedOption = decltype(options)::WeightedOption; + options + .add(FeatureSet::MVP, + WeightedOption{&Self::makeLocalSet, VeryImportant}, + WeightedOption{&Self::makeBlock, Important}, + WeightedOption{&Self::makeIf, Important}, + WeightedOption{&Self::makeLoop, Important}, + WeightedOption{&Self::makeBreak, Important}, + WeightedOption{&Self::makeStore, Important}, + &Self::makeCall, + &Self::makeCallIndirect, + &Self::makeDrop, + &Self::makeNop, + &Self::makeGlobalSet) + .add(FeatureSet::BulkMemory, &Self::makeBulkMemory) + .add(FeatureSet::Atomics, &Self::makeAtomic); return (this->*pick(options))(Type::none); } Expression* _makeunreachable() { - switch (upTo(15)) { - case 0: - return makeBlock(Type::unreachable); - case 1: - return makeIf(Type::unreachable); - case 2: - return makeLoop(Type::unreachable); - case 3: - return makeBreak(Type::unreachable); - case 4: - return makeCall(Type::unreachable); - case 5: - return makeCallIndirect(Type::unreachable); - case 6: - return makeLocalSet(Type::unreachable); - case 7: - return makeStore(Type::unreachable); - case 8: - return makeUnary(Type::unreachable); - case 9: - return makeBinary(Type::unreachable); - case 10: - return makeSelect(Type::unreachable); - case 11: - return makeSwitch(Type::unreachable); - case 12: - return makeDrop(Type::unreachable); - case 13: - return makeReturn(Type::unreachable); - case 14: - return makeUnreachable(Type::unreachable); - } - WASM_UNREACHABLE("unexpected value"); + using Self = TranslateToFuzzReader; + auto options = FeatureOptions<Expression* (Self::*)(Type)>(); + using WeightedOption = decltype(options)::WeightedOption; + options.add(FeatureSet::MVP, + WeightedOption{&Self::makeLocalSet, VeryImportant}, + WeightedOption{&Self::makeBlock, Important}, + WeightedOption{&Self::makeIf, Important}, + WeightedOption{&Self::makeLoop, Important}, + WeightedOption{&Self::makeBreak, Important}, + WeightedOption{&Self::makeStore, Important}, + WeightedOption{&Self::makeUnary, Important}, + WeightedOption{&Self::makeBinary, Important}, + WeightedOption{&Self::makeUnreachable, Important}, + &Self::makeCall, + &Self::makeCallIndirect, + &Self::makeSelect, + &Self::makeSwitch, + &Self::makeDrop, + &Self::makeReturn); + return (this->*pick(options))(Type::unreachable); } // make something with no chance of infinite recursion @@ -2891,6 +2849,20 @@ private: return add(feature, rest...); } + struct WeightedOption { + T option; + size_t weight; + }; + + template<typename... Ts> + FeatureOptions<T>& + add(FeatureSet feature, WeightedOption weightedOption, Ts... rest) { + for (size_t i = 0; i < weightedOption.weight; i++) { + options[feature].push_back(weightedOption.option); + } + return add(feature, rest...); + } + FeatureOptions<T>& add(FeatureSet feature) { return *this; } std::map<FeatureSet, std::vector<T>> options; |