#ifndef LLVM_FUZZMUTATE_OPDESCRIPTOR_H
#define LLVM_FUZZMUTATE_OPDESCRIPTOR_H
#include "llvm/ADT/ArrayRef.h"
#include "llvm/ADT/SmallVector.h"
#include "llvm/IR/Constants.h"
#include "llvm/IR/DerivedTypes.h"
#include "llvm/IR/Type.h"
#include "llvm/IR/Value.h"
#include <functional>
namespace llvm {
class Instruction;
namespace fuzzerop {
void makeConstantsWithType(Type *T, std::vector<Constant *> &Cs);
std::vector<Constant *> makeConstantsWithType(Type *T);
class SourcePred {
public:
using PredT = std::function<bool(ArrayRef<Value *> Cur, const Value *New)>;
using MakeT = std::function<std::vector<Constant *>(
ArrayRef<Value *> Cur, ArrayRef<Type *> BaseTypes)>;
private:
PredT Pred;
MakeT Make;
public:
SourcePred(PredT Pred, MakeT Make) : Pred(Pred), Make(Make) {}
SourcePred(PredT Pred, NoneType) : Pred(Pred) {
Make = [Pred](ArrayRef<Value *> Cur, ArrayRef<Type *> BaseTypes) {
std::vector<Constant *> Result;
for (Type *T : BaseTypes) {
Constant *V = UndefValue::get(T);
if (Pred(Cur, V))
makeConstantsWithType(T, Result);
}
if (Result.empty())
report_fatal_error("Predicate does not match for base types");
return Result;
};
}
bool matches(ArrayRef<Value *> Cur, const Value *New) {
return Pred(Cur, New);
}
std::vector<Constant *> generate(ArrayRef<Value *> Cur,
ArrayRef<Type *> BaseTypes) {
return Make(Cur, BaseTypes);
}
};
struct OpDescriptor {
unsigned Weight;
SmallVector<SourcePred, 2> SourcePreds;
std::function<Value *(ArrayRef<Value *>, Instruction *)> BuilderFunc;
};
static inline SourcePred onlyType(Type *Only) {
auto Pred = [Only](ArrayRef<Value *>, const Value *V) {
return V->getType() == Only;
};
auto Make = [Only](ArrayRef<Value *>, ArrayRef<Type *>) {
return makeConstantsWithType(Only);
};
return {Pred, Make};
}
static inline SourcePred anyType() {
auto Pred = [](ArrayRef<Value *>, const Value *V) {
return !V->getType()->isVoidTy();
};
auto Make = None;
return {Pred, Make};
}
static inline SourcePred anyIntType() {
auto Pred = [](ArrayRef<Value *>, const Value *V) {
return V->getType()->isIntegerTy();
};
auto Make = None;
return {Pred, Make};
}
static inline SourcePred anyFloatType() {
auto Pred = [](ArrayRef<Value *>, const Value *V) {
return V->getType()->isFloatingPointTy();
};
auto Make = None;
return {Pred, Make};
}
static inline SourcePred anyPtrType() {
auto Pred = [](ArrayRef<Value *>, const Value *V) {
return V->getType()->isPointerTy() && !V->isSwiftError();
};
auto Make = [](ArrayRef<Value *>, ArrayRef<Type *> Ts) {
std::vector<Constant *> Result;
for (Type *T : Ts)
Result.push_back(UndefValue::get(PointerType::getUnqual(T)));
return Result;
};
return {Pred, Make};
}
static inline SourcePred sizedPtrType() {
auto Pred = [](ArrayRef<Value *>, const Value *V) {
if (V->isSwiftError())
return false;
if (const auto *PtrT = dyn_cast<PointerType>(V->getType()))
return PtrT->isOpaque() ||
PtrT->getNonOpaquePointerElementType()->isSized();
return false;
};
auto Make = [](ArrayRef<Value *>, ArrayRef<Type *> Ts) {
std::vector<Constant *> Result;
for (Type *T : Ts)
if (T->isSized())
Result.push_back(UndefValue::get(PointerType::getUnqual(T)));
return Result;
};
return {Pred, Make};
}
static inline SourcePred anyAggregateType() {
auto Pred = [](ArrayRef<Value *>, const Value *V) {
if (isa<ArrayType>(V->getType()))
return V->getType()->getArrayNumElements() > 0;
if (isa<StructType>(V->getType()))
return V->getType()->getStructNumElements() > 0;
return V->getType()->isAggregateType();
};
auto Find = None;
return {Pred, Find};
}
static inline SourcePred anyVectorType() {
auto Pred = [](ArrayRef<Value *>, const Value *V) {
return V->getType()->isVectorTy();
};
auto Make = None;
return {Pred, Make};
}
static inline SourcePred matchFirstType() {
auto Pred = [](ArrayRef<Value *> Cur, const Value *V) {
assert(!Cur.empty() && "No first source yet");
return V->getType() == Cur[0]->getType();
};
auto Make = [](ArrayRef<Value *> Cur, ArrayRef<Type *>) {
assert(!Cur.empty() && "No first source yet");
return makeConstantsWithType(Cur[0]->getType());
};
return {Pred, Make};
}
static inline SourcePred matchScalarOfFirstType() {
auto Pred = [](ArrayRef<Value *> Cur, const Value *V) {
assert(!Cur.empty() && "No first source yet");
return V->getType() == Cur[0]->getType()->getScalarType();
};
auto Make = [](ArrayRef<Value *> Cur, ArrayRef<Type *>) {
assert(!Cur.empty() && "No first source yet");
return makeConstantsWithType(Cur[0]->getType()->getScalarType());
};
return {Pred, Make};
}
} }
#endif