aboutsummaryrefslogtreecommitdiff
path: root/lib/Transforms/NaCl/InsertDivideCheck.cpp
blob: f1deae618f4148075c943ffa8f1409db624a2fd2 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
//===- InsertDivideCheck.cpp - Add divide by zero checks ------------------===//
//
//                     The LLVM Compiler Infrastructure
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
//
// This pass adds a check for divide by zero before every integer DIV or REM.
//
//===----------------------------------------------------------------------===//

#define DEBUG_TYPE "add-divide-check"
#include "llvm/ADT/SmallPtrSet.h"
#include "llvm/ADT/STLExtras.h"
#include "llvm/IR/BasicBlock.h"
#include "llvm/IR/Constants.h"
#include "llvm/IR/Function.h"
#include "llvm/IR/Instructions.h"
#include "llvm/IR/Intrinsics.h"
#include "llvm/IR/LLVMContext.h"
#include "llvm/Pass.h"
#include "llvm/Support/CFG.h"
#include "llvm/Transforms/NaCl.h"

using namespace llvm;

namespace {
  class InsertDivideCheck : public FunctionPass {
  public:
    static char ID;
    InsertDivideCheck() : FunctionPass(ID) {
      initializeInsertDivideCheckPass(*PassRegistry::getPassRegistry());
    }

    bool runOnFunction(Function &F);
  };
}

static BasicBlock *CreateTrapBlock(Function &F, DebugLoc dl) {
  BasicBlock *TrapBlock = BasicBlock::Create(F.getContext(), "divrem.by.zero",
                                             &F);
  Value *TrapFn = Intrinsic::getDeclaration(F.getParent(), Intrinsic::trap);
  CallInst::Create(TrapFn, "", TrapBlock)->setDebugLoc(dl);
  (new UnreachableInst(F.getContext(), TrapBlock))->setDebugLoc(dl);
  return TrapBlock;
}

bool InsertDivideCheck::runOnFunction(Function &F) {
  SmallPtrSet<Instruction*, 8> GuardedDivs;
  // If the pass finds a DIV/REM that needs to be checked for zero denominator,
  // it will insert a new "trap" block, and split the block that contains the
  // DIV/REM into two blocks.  The new BasicBlocks are added after the current
  // BasicBlock, so that if there is more than one DIV/REM in the same block,
  // all are visited.
  for (Function::iterator I = F.begin(); I != F.end(); I++) {
    BasicBlock *BB = I;

    for (BasicBlock::iterator BI = BB->begin(), BE = BB->end();
         BI != BE; BI++) {
      BinaryOperator *DivInst = dyn_cast<BinaryOperator>(BI);
      if (!DivInst || (GuardedDivs.count(DivInst) != 0))
        continue;
      unsigned Opcode = DivInst->getOpcode();
      if (Opcode != Instruction::SDiv && Opcode != Instruction::UDiv &&
          Opcode != Instruction::SRem && Opcode != Instruction::URem)
        continue;
      Value *Denominator = DivInst->getOperand(1);
      if (!Denominator->getType()->isIntegerTy())
        continue;
      DebugLoc dl = DivInst->getDebugLoc();
      if (ConstantInt *DenomConst = dyn_cast<ConstantInt>(Denominator)) {
        // Divides by constants do not need a denominator test.
        if (DenomConst->isZero()) {
          // For explicit divides by zero, insert a trap before DIV/REM
          Value *TrapFn = Intrinsic::getDeclaration(F.getParent(),
                                                    Intrinsic::trap);
          CallInst::Create(TrapFn, "", DivInst)->setDebugLoc(dl);
        }
        continue;
      }
      // Create a trap block.
      BasicBlock *TrapBlock = CreateTrapBlock(F, dl);
      // Move instructions in BB from DivInst to BB's end to a new block.
      BasicBlock *Successor = BB->splitBasicBlock(BI, "guarded.divrem");
      // Remove the unconditional branch inserted by splitBasicBlock.
      BB->getTerminator()->eraseFromParent();
      // Remember that DivInst was already processed, so that when we process
      // inserted blocks later, we do not attempt to again guard it.
      GuardedDivs.insert(DivInst);
      // Compare the denominator with zero.
      Value *Zero = ConstantInt::get(Denominator->getType(), 0);
      Value *DenomIsZero = new ICmpInst(*BB, ICmpInst::ICMP_EQ, Denominator,
                                        Zero, "");
      // Put in a condbranch to the trap block.
      BranchInst::Create(TrapBlock, Successor, DenomIsZero, BB);
      // BI is invalidated when we split.  Stop the BasicBlock iterator.
      break;
    }
  }

  return false;
}

char InsertDivideCheck::ID = 0;
INITIALIZE_PASS(InsertDivideCheck, "insert-divide-check",
                "Insert divide by zero checks", false, false)

FunctionPass *llvm::createInsertDivideCheckPass() {
  return new InsertDivideCheck();
}