File indexing completed on 2026-05-10 08:43:56
0001
0002
0003
0004
0005
0006
0007
0008
0009
0010
0011
0012
0013
0014 #ifndef LLVM_FUZZMUTATE_OPDESCRIPTOR_H
0015 #define LLVM_FUZZMUTATE_OPDESCRIPTOR_H
0016
0017 #include "llvm/ADT/ArrayRef.h"
0018 #include "llvm/ADT/SmallVector.h"
0019 #include "llvm/IR/Constants.h"
0020 #include "llvm/IR/DerivedTypes.h"
0021 #include "llvm/IR/InstrTypes.h"
0022 #include "llvm/IR/Type.h"
0023 #include "llvm/IR/Value.h"
0024 #include <functional>
0025
0026 namespace llvm {
0027 class Instruction;
0028 namespace fuzzerop {
0029
0030
0031
0032 void makeConstantsWithType(Type *T, std::vector<Constant *> &Cs);
0033 std::vector<Constant *> makeConstantsWithType(Type *T);
0034
0035
0036
0037
0038
0039
0040
0041
0042
0043 class SourcePred {
0044 public:
0045
0046
0047 using PredT = std::function<bool(ArrayRef<Value *> Cur, const Value *New)>;
0048
0049
0050
0051 using MakeT = std::function<std::vector<Constant *>(
0052 ArrayRef<Value *> Cur, ArrayRef<Type *> BaseTypes)>;
0053
0054 private:
0055 PredT Pred;
0056 MakeT Make;
0057
0058 public:
0059
0060 SourcePred(PredT Pred, MakeT Make) : Pred(Pred), Make(Make) {}
0061 SourcePred(PredT Pred, std::nullopt_t) : Pred(Pred) {
0062 Make = [Pred](ArrayRef<Value *> Cur, ArrayRef<Type *> BaseTypes) {
0063
0064 std::vector<Constant *> Result;
0065 for (Type *T : BaseTypes) {
0066 Constant *V = PoisonValue::get(T);
0067 if (Pred(Cur, V))
0068 makeConstantsWithType(T, Result);
0069 }
0070 if (Result.empty())
0071 report_fatal_error("Predicate does not match for base types");
0072 return Result;
0073 };
0074 }
0075
0076
0077 bool matches(ArrayRef<Value *> Cur, const Value *New) {
0078 return Pred(Cur, New);
0079 }
0080
0081
0082 std::vector<Constant *> generate(ArrayRef<Value *> Cur,
0083 ArrayRef<Type *> BaseTypes) {
0084 return Make(Cur, BaseTypes);
0085 }
0086 };
0087
0088
0089 struct OpDescriptor {
0090 unsigned Weight;
0091 SmallVector<SourcePred, 2> SourcePreds;
0092 std::function<Value *(ArrayRef<Value *>, BasicBlock::iterator)> BuilderFunc;
0093 };
0094
0095 static inline SourcePred onlyType(Type *Only) {
0096 auto Pred = [Only](ArrayRef<Value *>, const Value *V) {
0097 return V->getType() == Only;
0098 };
0099 auto Make = [Only](ArrayRef<Value *>, ArrayRef<Type *>) {
0100 return makeConstantsWithType(Only);
0101 };
0102 return {Pred, Make};
0103 }
0104
0105 static inline SourcePred anyType() {
0106 auto Pred = [](ArrayRef<Value *>, const Value *V) {
0107 return !V->getType()->isVoidTy();
0108 };
0109 auto Make = std::nullopt;
0110 return {Pred, Make};
0111 }
0112
0113 static inline SourcePred anyIntType() {
0114 auto Pred = [](ArrayRef<Value *>, const Value *V) {
0115 return V->getType()->isIntegerTy();
0116 };
0117 auto Make = std::nullopt;
0118 return {Pred, Make};
0119 }
0120
0121 static inline SourcePred anyIntOrVecIntType() {
0122 auto Pred = [](ArrayRef<Value *>, const Value *V) {
0123 return V->getType()->isIntOrIntVectorTy();
0124 };
0125 return {Pred, std::nullopt};
0126 }
0127
0128 static inline SourcePred boolOrVecBoolType() {
0129 auto Pred = [](ArrayRef<Value *>, const Value *V) {
0130 return V->getType()->isIntOrIntVectorTy(1);
0131 };
0132 return {Pred, std::nullopt};
0133 }
0134
0135 static inline SourcePred anyFloatType() {
0136 auto Pred = [](ArrayRef<Value *>, const Value *V) {
0137 return V->getType()->isFloatingPointTy();
0138 };
0139 auto Make = std::nullopt;
0140 return {Pred, Make};
0141 }
0142
0143 static inline SourcePred anyFloatOrVecFloatType() {
0144 auto Pred = [](ArrayRef<Value *>, const Value *V) {
0145 return V->getType()->isFPOrFPVectorTy();
0146 };
0147 return {Pred, std::nullopt};
0148 }
0149
0150 static inline SourcePred anyPtrType() {
0151 auto Pred = [](ArrayRef<Value *>, const Value *V) {
0152 return V->getType()->isPointerTy() && !V->isSwiftError();
0153 };
0154 auto Make = [](ArrayRef<Value *>, ArrayRef<Type *> Ts) {
0155 std::vector<Constant *> Result;
0156
0157 for (Type *T : Ts)
0158 Result.push_back(
0159 PoisonValue::get(PointerType::getUnqual(T->getContext())));
0160 return Result;
0161 };
0162 return {Pred, Make};
0163 }
0164
0165 static inline SourcePred sizedPtrType() {
0166 auto Pred = [](ArrayRef<Value *>, const Value *V) {
0167 if (V->isSwiftError())
0168 return false;
0169
0170 return V->getType()->isPointerTy();
0171 };
0172 auto Make = [](ArrayRef<Value *>, ArrayRef<Type *> Ts) {
0173 std::vector<Constant *> Result;
0174
0175
0176
0177 for (Type *T : Ts)
0178 if (T->isSized())
0179 Result.push_back(
0180 PoisonValue::get(PointerType::getUnqual(T->getContext())));
0181
0182 return Result;
0183 };
0184 return {Pred, Make};
0185 }
0186
0187 static inline SourcePred matchFirstLengthWAnyType() {
0188 auto Pred = [](ArrayRef<Value *> Cur, const Value *V) {
0189 assert(!Cur.empty() && "No first source yet");
0190 Type *This = V->getType(), *First = Cur[0]->getType();
0191 VectorType *ThisVec = dyn_cast<VectorType>(This);
0192 VectorType *FirstVec = dyn_cast<VectorType>(First);
0193 if (ThisVec && FirstVec) {
0194 return ThisVec->getElementCount() == FirstVec->getElementCount();
0195 }
0196 return (ThisVec == nullptr) && (FirstVec == nullptr) && (!This->isVoidTy());
0197 };
0198 auto Make = [](ArrayRef<Value *> Cur, ArrayRef<Type *> BaseTypes) {
0199 assert(!Cur.empty() && "No first source yet");
0200 std::vector<Constant *> Result;
0201 ElementCount EC;
0202 bool isVec = false;
0203 if (VectorType *VecTy = dyn_cast<VectorType>(Cur[0]->getType())) {
0204 EC = VecTy->getElementCount();
0205 isVec = true;
0206 }
0207 for (Type *T : BaseTypes) {
0208 if (VectorType::isValidElementType(T)) {
0209 if (isVec)
0210
0211 makeConstantsWithType(VectorType::get(T, EC), Result);
0212 else
0213 makeConstantsWithType(T, Result);
0214 }
0215 }
0216 assert(!Result.empty() && "No potential constants.");
0217 return Result;
0218 };
0219 return {Pred, Make};
0220 }
0221
0222
0223 static inline SourcePred matchSecondType() {
0224 auto Pred = [](ArrayRef<Value *> Cur, const Value *V) {
0225 assert((Cur.size() > 1) && "No second source yet");
0226 return V->getType() == Cur[1]->getType();
0227 };
0228 auto Make = [](ArrayRef<Value *> Cur, ArrayRef<Type *>) {
0229 assert((Cur.size() > 1) && "No second source yet");
0230 return makeConstantsWithType(Cur[1]->getType());
0231 };
0232 return {Pred, Make};
0233 }
0234
0235 static inline SourcePred anyAggregateType() {
0236 auto Pred = [](ArrayRef<Value *>, const Value *V) {
0237
0238 if (isa<ArrayType>(V->getType()))
0239 return V->getType()->getArrayNumElements() > 0;
0240
0241
0242 if (isa<StructType>(V->getType()))
0243 return V->getType()->getStructNumElements() > 0;
0244
0245 return V->getType()->isAggregateType();
0246 };
0247
0248
0249 auto Find = std::nullopt;
0250 return {Pred, Find};
0251 }
0252
0253 static inline SourcePred anyVectorType() {
0254 auto Pred = [](ArrayRef<Value *>, const Value *V) {
0255 return V->getType()->isVectorTy();
0256 };
0257
0258
0259
0260 auto Make = std::nullopt;
0261 return {Pred, Make};
0262 }
0263
0264
0265 static inline SourcePred matchFirstType() {
0266 auto Pred = [](ArrayRef<Value *> Cur, const Value *V) {
0267 assert(!Cur.empty() && "No first source yet");
0268 return V->getType() == Cur[0]->getType();
0269 };
0270 auto Make = [](ArrayRef<Value *> Cur, ArrayRef<Type *>) {
0271 assert(!Cur.empty() && "No first source yet");
0272 return makeConstantsWithType(Cur[0]->getType());
0273 };
0274 return {Pred, Make};
0275 }
0276
0277
0278 static inline SourcePred matchScalarOfFirstType() {
0279 auto Pred = [](ArrayRef<Value *> Cur, const Value *V) {
0280 assert(!Cur.empty() && "No first source yet");
0281 return V->getType() == Cur[0]->getType()->getScalarType();
0282 };
0283 auto Make = [](ArrayRef<Value *> Cur, ArrayRef<Type *>) {
0284 assert(!Cur.empty() && "No first source yet");
0285 return makeConstantsWithType(Cur[0]->getType()->getScalarType());
0286 };
0287 return {Pred, Make};
0288 }
0289
0290 }
0291 }
0292
0293 #endif