[FuzzMutate] Allow only sized pointers for the GEP instruction

Differential Revision: https://reviews.llvm.org/D40837



git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@320032 91177308-0d34-0410-b5e6-96231b3b80d8
This commit is contained in:
Igor Laevsky 2017-12-07 11:10:11 +00:00
parent b8b865bdd8
commit 9fb4bebf8e
3 changed files with 66 additions and 1 deletions

View File

@ -140,6 +140,24 @@ static inline SourcePred anyPtrType() {
return {Pred, Make};
}
static inline SourcePred sizedPtrType() {
auto Pred = [](ArrayRef<Value *>, const Value *V) {
if (const auto *PtrT = dyn_cast<PointerType>(V->getType()))
return PtrT->getElementType()->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) {
return V->getType()->isAggregateType();

View File

@ -172,7 +172,7 @@ OpDescriptor llvm::fuzzerop::gepDescriptor(unsigned Weight) {
// TODO: Handle aggregates and vectors
// TODO: Support multiple indices.
// TODO: Try to avoid meaningless accesses.
return {Weight, {anyPtrType(), anyIntType()}, buildGEP};
return {Weight, {sizedPtrType(), anyIntType()}, buildGEP};
}
static uint64_t getAggregateNumElements(Type *T) {

View File

@ -8,11 +8,13 @@
//===----------------------------------------------------------------------===//
#include "llvm/FuzzMutate/Operations.h"
#include "llvm/AsmParser/Parser.h"
#include "llvm/FuzzMutate/OpDescriptor.h"
#include "llvm/IR/Constants.h"
#include "llvm/IR/Instructions.h"
#include "llvm/IR/Module.h"
#include "llvm/IR/Verifier.h"
#include "llvm/Support/SourceMgr.h"
#include "gmock/gmock.h"
#include "gtest/gtest.h"
#include <iostream>
@ -52,9 +54,25 @@ using testing::NotNull;
using testing::PrintToString;
using testing::SizeIs;
namespace {
std::unique_ptr<Module> parseAssembly(
const char *Assembly, LLVMContext &Context) {
SMDiagnostic Error;
std::unique_ptr<Module> M = parseAssemblyString(Assembly, Error, Context);
std::string ErrMsg;
raw_string_ostream OS(ErrMsg);
Error.print("", OS);
assert(M && !verifyModule(*M, &errs()));
return M;
}
MATCHER_P(TypesMatch, V, "has type " + PrintToString(V->getType())) {
return arg->getType() == V->getType();
}
MATCHER_P(HasType, T, "") { return arg->getType() == T; }
TEST(OperationsTest, SourcePreds) {
@ -253,6 +271,33 @@ TEST(OperationsTest, GEP) {
EXPECT_FALSE(verifyModule(M, &errs()));
}
TEST(OperationsTest, GEPPointerOperand) {
// Check that we only pick sized pointers for the GEP instructions
LLVMContext Ctx;
const char *SourceCode =
"declare void @f()\n"
"define void @test() {\n"
" %v = bitcast void ()* @f to i64 (i8 addrspace(4)*)*\n"
" %a = alloca i64, i32 10\n"
" ret void\n"
"}";
auto M = parseAssembly(SourceCode, Ctx);
fuzzerop::OpDescriptor Descr = fuzzerop::gepDescriptor(1);
// Get first basic block of the test function
Function &F = *M->getFunction("test");
BasicBlock &BB = *F.begin();
// Don't match %v
ASSERT_FALSE(Descr.SourcePreds[0].matches({}, &*BB.begin()));
// Match %a
ASSERT_TRUE(Descr.SourcePreds[0].matches({}, &*std::next(BB.begin())));
}
TEST(OperationsTest, ExtractAndInsertValue) {
LLVMContext Ctx;
@ -321,3 +366,5 @@ TEST(OperationsTest, ExtractAndInsertValue) {
IVOp.SourcePreds[2].generate({SVal, ConstantInt::get(Int32Ty, 0)}, {}),
ElementsAre(ConstantInt::get(Int32Ty, 1)));
}
}