Skip to content

Commit

Permalink
Logical mutations: fix 'dangling' incoming phi-node value
Browse files Browse the repository at this point in the history
  • Loading branch information
AlexDenisov authored and AlexDenisov committed May 5, 2022
1 parent 57ce918 commit 97c37ca
Show file tree
Hide file tree
Showing 6 changed files with 66 additions and 9 deletions.
3 changes: 2 additions & 1 deletion include/mull/Mutators/CXX/LogicalAndToOr.h
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@ namespace llvm {
class BasicBlock;
class BranchInst;
class Instruction;
class PHINode;
} // namespace llvm

using namespace llvm;
Expand All @@ -24,8 +25,8 @@ namespace mull {
class Bitcode;
class MutationPoint;
class MutationPointAddress;
class ReachableFunction;
namespace cxx {
void cleanupIncomingValues(llvm::PHINode &phi);

class LogicalAndToOr : public Mutator {

Expand Down
4 changes: 2 additions & 2 deletions include/mull/Mutators/CXX/LogicalOrToAnd.h
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@ namespace llvm {
class BasicBlock;
class BranchInst;
class Instruction;
class PHINode;
} // namespace llvm

using namespace llvm;
Expand All @@ -24,10 +25,9 @@ namespace mull {
class Bitcode;
class MutationPoint;
class MutationPointAddress;
class ReachableFunction;

namespace cxx {

void cleanupIncomingValues(llvm::PHINode &phi);
class LogicalOrToAnd : public Mutator {

static OR_AND_MutationType findPossibleMutation(Value &V);
Expand Down
31 changes: 28 additions & 3 deletions lib/Mutators/CXX/LogicalAndToOr.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@
#include "mull/SourceLocation.h"

#include <iterator>
#include <llvm/IR/CFG.h>
#include <llvm/IR/Constants.h>
#include <llvm/IR/DebugInfoMetadata.h>
#include <llvm/IR/InstIterator.h>
Expand All @@ -22,6 +23,24 @@ std::string LogicalAndToOr::description() {
return "Replaces && with ||";
}

void mull::cxx::cleanupIncomingValues(llvm::PHINode &phi) {
std::unordered_set<llvm::BasicBlock *> preds;
for (auto pred : predecessors(phi.getParent())) {
preds.insert(pred);
}
std::unordered_set<llvm::BasicBlock *> toRemove;
for (auto &incoming : phi.incoming_values()) {
auto basicBlock = phi.getIncomingBlock(incoming);
if (!preds.count(basicBlock)) {
toRemove.insert(basicBlock);
}
}

for (auto basicBlock : toRemove) {
phi.removeIncomingValue(basicBlock);
}
}

AND_OR_MutationType LogicalAndToOr::findPossibleMutation(Value &V) {
auto *branchInst = dyn_cast<BranchInst>(&V);

Expand Down Expand Up @@ -53,15 +72,21 @@ void LogicalAndToOr::applyMutation(llvm::Function *function, const MutationPoint
findPossibleMutationInBranch(branchInst, &secondBranch);

if (possibleMutationType == AND_OR_MutationType_AND_to_OR_Pattern1) {
return applyMutationANDToOR_Pattern1(branchInst, secondBranch);
applyMutationANDToOR_Pattern1(branchInst, secondBranch);
}

if (possibleMutationType == AND_OR_MutationType_AND_to_OR_Pattern2) {
return applyMutationANDToOR_Pattern2(branchInst, secondBranch);
applyMutationANDToOR_Pattern2(branchInst, secondBranch);
}

if (possibleMutationType == AND_OR_MutationType_AND_to_OR_Pattern3) {
return applyMutationANDToOR_Pattern3(branchInst, secondBranch);
applyMutationANDToOR_Pattern3(branchInst, secondBranch);
}

for (auto &instruction : llvm::instructions(function)) {
if (llvm::isa<llvm::PHINode>(instruction)) {
cleanupIncomingValues(llvm::cast<llvm::PHINode>(instruction));
}
}
}

Expand Down
11 changes: 8 additions & 3 deletions lib/Mutators/CXX/LogicalOrToAnd.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -53,15 +53,20 @@ void LogicalOrToAnd::applyMutation(llvm::Function *function, const MutationPoint
findPossibleMutationInBranch(branchInst, &secondBranch);

if (possibleMutationType == OR_AND_MutationType_OR_to_AND_Pattern1) {
return applyMutationORToAND_Pattern1(branchInst, secondBranch);
applyMutationORToAND_Pattern1(branchInst, secondBranch);
}

if (possibleMutationType == OR_AND_MutationType_OR_to_AND_Pattern2) {
return applyMutationORToAND_Pattern2(branchInst, secondBranch);
applyMutationORToAND_Pattern2(branchInst, secondBranch);
}

if (possibleMutationType == OR_AND_MutationType_OR_to_AND_Pattern3) {
return applyMutationORToAND_Pattern3(branchInst, secondBranch);
applyMutationORToAND_Pattern3(branchInst, secondBranch);
}
for (auto &instruction : llvm::instructions(function)) {
if (llvm::isa<llvm::PHINode>(instruction)) {
cleanupIncomingValues(llvm::cast<llvm::PHINode>(instruction));
}
}
}

Expand Down
23 changes: 23 additions & 0 deletions tests-lit/tests/mutations/logical/phi_nodes/main.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
// clang-format off

int main() {
int a = 1;
a = a && a && a;
int b = 2;
b = b || b || b;
return 0;
}

// RUN: %clang_cc %sysroot -O0 %pass_mull_ir_frontend -g %s -o %s.exe
// RUN: unset TERM; %mull_runner -reporters=IDE %s.exe | %filecheck %s --dump-input=fail
// CHECK:[info] Survived mutants (3/3):
// CHECK-NEXT:{{.*}}main.c:5:9: warning: Survived: Replaced && with || [cxx_logical_and_to_or]
// CHECK-NEXT: a = a && a && a;
// CHECK-NEXT: ^
// CHECK-NEXT:{{.*}}main.c:5:14: warning: Survived: Replaced && with || [cxx_logical_and_to_or]
// CHECK-NEXT: a = a && a && a;
// CHECK-NEXT: ^
// CHECK-NEXT:{{.*}}main.c:7:9: warning: Survived: Replaced || with && [cxx_logical_or_to_and]
// CHECK-NEXT: b = b || b || b;
// CHECK-NEXT: ^
// CHECK-NEXT:[info] Mutation score: 0%
3 changes: 3 additions & 0 deletions tests-lit/tests/mutations/logical/phi_nodes/mull.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
mutators:
- cxx_logical_and_to_or
- cxx_logical_or_to_and

0 comments on commit 97c37ca

Please sign in to comment.