blob: b26b00d971ba82754b783ab74671a0b8818c178a [file] [log] [blame] [edit]
/*
* Copyright 2020 Google LLC
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#ifndef INCLUDE_EXPR_GEN_H
#define INCLUDE_EXPR_GEN_H
#include <array>
#include <cstdint>
#include <optional>
#include <random>
#include <unordered_map>
#include "tools/fuzzer/ast.h"
#include "tools/fuzzer/enum_bitset.h"
namespace fuzzer {
enum class ExprKind : unsigned char {
EnumFirst,
IntegerConstant = EnumFirst,
DoubleConstant,
VariableExpr,
UnaryExpr,
BinaryExpr,
AddressOf,
MemberOf,
MemberOfPtr,
ArrayIndex,
TernaryExpr,
BooleanConstant,
DereferenceExpr,
CastExpr,
EnumLast = CastExpr,
};
inline constexpr size_t NUM_GEN_EXPR_KINDS = (size_t)ExprKind::EnumLast + 1;
enum class TypeKind : unsigned char {
EnumFirst,
ScalarType = EnumFirst,
TaggedType,
PointerType,
VoidPointerType,
EnumLast = VoidPointerType,
};
inline constexpr size_t NUM_GEN_TYPE_KINDS = (size_t)TypeKind::EnumLast + 1;
using ExprKindMask = EnumBitset<ExprKind>;
using TypeKindMask = EnumBitset<TypeKind>;
class Weights;
class ExprConstraints;
class TypeConstraints;
struct ExprKindWeightInfo {
float initial_weight;
float dampening_factor;
};
struct TypeKindWeightInfo {
float initial_weight;
float dampening_factor;
};
using BinOpMask = EnumBitset<BinOp>;
using UnOpMask = EnumBitset<UnOp>;
struct GenConfig {
int num_exprs_to_generate = 30;
uint64_t int_const_min = 0;
uint64_t int_const_max = 1000;
double double_constant_min = 0;
double double_constant_max = 10;
float parenthesize_prob = 0.2f;
float binop_gen_ptr_expr_prob = 0.2f;
float binop_gen_ptrdiff_expr_prob = 0.1f;
float binop_flip_operands_prob = 0.1f;
float const_prob = 0.3f;
float volatile_prob = 0.05f;
BinOpMask bin_op_mask = BinOpMask::all_set();
UnOpMask un_op_mask = UnOpMask::all_set();
ExprKindMask expr_kind_mask = ExprKindMask::all_set();
std::array<ExprKindWeightInfo, NUM_GEN_EXPR_KINDS> expr_kind_weights = {{
{1.0f, 0.0f}, // ExprKind::IntegerConstant
{2.0f, 0.0f}, // ExprKind::DoubleConstant
{1.0f, 0.0f}, // ExprKind::VariableExpr
{7.0f, 0.4f}, // ExprKind::UnaryExpr
{3.0f, 0.4f}, // ExprKind::BinaryExpr
{1.0f, 0.1f}, // ExprKind::AddressOf
{1.0f, 0.1f}, // ExprKind::MemberOf
{1.0f, 0.1f}, // ExprKind::MemberOfPtr
{1.0f, 0.1f}, // ExprKind::ArrayIndex
{1.0f, 0.1f}, // ExprKind::TernaryExpr
{1.0f, 0.0f}, // ExprKind::BooleanConstant
{1.0f, 0.1f}, // ExprKind::DereferenceExpr
{1.0f, 0.4f}, // ExprKind::CastExpr
}};
std::array<TypeKindWeightInfo, NUM_GEN_TYPE_KINDS> type_kind_weights = {{
{2.0f, 0.0f}, // TypeKind::ScalarType
{1.0f, 0.0f}, // TypeKind::TaggedType
{1.0f, 0.1f}, // TypeKind::PointerType
{1.0f, 0.1f}, // TypeKind::VoidPointerType
}};
std::unordered_map<Type, std::vector<std::string>> symbol_table;
};
class GeneratorRng {
public:
virtual ~GeneratorRng() {}
virtual BinOp gen_bin_op(BinOpMask mask) = 0;
virtual UnOp gen_un_op(UnOpMask mask) = 0;
virtual ExprKind gen_expr_kind(const Weights& weights,
const ExprKindMask& mask) = 0;
virtual TypeKind gen_type_kind(const Weights& weights,
const TypeKindMask& mask) = 0;
virtual ScalarType gen_scalar_type(EnumBitset<ScalarType> mask) = 0;
virtual bool gen_boolean() = 0;
virtual IntegerConstant gen_integer_constant(uint64_t min, uint64_t max) = 0;
virtual DoubleConstant gen_double_constant(double min, double max) = 0;
virtual bool gen_parenthesize(float probability) = 0;
virtual bool gen_binop_ptr_expr(float probability) = 0;
virtual bool gen_binop_flip_operands(float probability) = 0;
virtual bool gen_binop_ptrdiff_expr(float probability) = 0;
virtual CvQualifiers gen_cv_qualifiers(float const_prob,
float volatile_prob) = 0;
};
class DefaultGeneratorRng : public GeneratorRng {
public:
explicit DefaultGeneratorRng(uint32_t seed) : rng_(seed) {}
BinOp gen_bin_op(BinOpMask mask) override;
UnOp gen_un_op(UnOpMask mask) override;
ExprKind gen_expr_kind(const Weights& weights,
const ExprKindMask& mask) override;
TypeKind gen_type_kind(const Weights& weights,
const TypeKindMask& mask) override;
ScalarType gen_scalar_type(EnumBitset<ScalarType> mask) override;
bool gen_boolean() override;
IntegerConstant gen_integer_constant(uint64_t min, uint64_t max) override;
DoubleConstant gen_double_constant(double min, double max) override;
bool gen_parenthesize(float probability) override;
bool gen_binop_ptr_expr(float probability) override;
bool gen_binop_flip_operands(float probability) override;
bool gen_binop_ptrdiff_expr(float probability) override;
CvQualifiers gen_cv_qualifiers(float const_prob,
float volatile_prob) override;
private:
std::mt19937 rng_;
};
class ExprGenerator {
public:
ExprGenerator(std::unique_ptr<GeneratorRng> rng, GenConfig cfg)
: rng_(std::move(rng)), cfg_(std::move(cfg)) {}
std::optional<Expr> generate();
private:
Expr maybe_parenthesized(Expr expr);
std::optional<Expr> gen_boolean_constant(const ExprConstraints& constraints);
std::optional<Expr> gen_integer_constant(const ExprConstraints& constraints);
std::optional<Expr> gen_double_constant(const ExprConstraints& constraints);
std::optional<Expr> gen_variable_expr(const ExprConstraints& constraints);
std::optional<Expr> gen_binary_expr(const Weights& weights,
const ExprConstraints& constraints);
std::optional<Expr> gen_unary_expr(const Weights& weights,
const ExprConstraints& constraints);
std::optional<Expr> gen_ternary_expr(const Weights& weights,
const ExprConstraints& constraints);
std::optional<Expr> gen_cast_expr(const Weights& weights,
const ExprConstraints& constraints);
std::optional<Expr> gen_dereference_expr(const Weights& weights,
const ExprConstraints& constraints);
std::optional<Expr> gen_address_of_expr(const Weights& weights,
const ExprConstraints& constraints);
std::optional<Expr> gen_member_of_expr(const Weights& weights,
const ExprConstraints& constraints);
std::optional<Expr> gen_member_of_ptr_expr(
const Weights& weights, const ExprConstraints& constraints);
std::optional<Expr> gen_array_index_expr(const Weights& weights,
const ExprConstraints& constraints);
std::optional<Type> gen_type(const Weights& weights,
const TypeConstraints& constraints);
std::optional<Type> gen_type_impl(const Weights& weights,
const TypeConstraints& constraints);
std::optional<QualifiedType> gen_qualified_type(
const Weights& weights, const TypeConstraints& constraints);
std::optional<Type> gen_pointer_type(const Weights& weights,
const TypeConstraints& constraints);
std::optional<Type> gen_void_pointer_type(const TypeConstraints& constraints);
std::optional<Type> gen_tagged_type(const TypeConstraints& constraints);
std::optional<Type> gen_scalar_type(const TypeConstraints& constraints);
CvQualifiers gen_cv_qualifiers();
std::optional<Expr> gen_with_weights(const Weights& weights,
const ExprConstraints& constraints);
private:
std::unique_ptr<GeneratorRng> rng_;
GenConfig cfg_;
};
} // namespace fuzzer
#endif // INCLUDE_EXPR_GEN_H