Index: include/llvm/InitializePasses.h =================================================================== --- include/llvm/InitializePasses.h +++ include/llvm/InitializePasses.h @@ -73,7 +73,7 @@ void initializeBasicAAWrapperPassPass(PassRegistry&); void initializeBlockExtractorPassPass(PassRegistry&); void initializeBlockFrequencyInfoWrapperPassPass(PassRegistry&); -void initializeBoundsCheckingPass(PassRegistry&); +void initializeBoundsCheckingLegacyPass(PassRegistry&); void initializeBranchFolderPassPass(PassRegistry&); void initializeBranchProbabilityInfoWrapperPassPass(PassRegistry&); void initializeBreakCriticalEdgesPass(PassRegistry&); Index: include/llvm/Transforms/Instrumentation/BoundsChecking.h =================================================================== --- /dev/null +++ include/llvm/Transforms/Instrumentation/BoundsChecking.h @@ -0,0 +1,48 @@ +//===- BoundsChecking.h - Instrumentation for run-time bounds checking --===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This file implements a pass that instruments the code to perform run-time +// bounds checking on loads, stores, and other memory intrinsics. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_TRANSFORMS_BOUNDSCHECKING_H +#define LLVM_TRANSFORMS_BOUNDSCHECKING_H + +#include "llvm/Analysis/MemoryBuiltins.h" +#include "llvm/Analysis/TargetFolder.h" +#include "llvm/IR/IRBuilder.h" +#include "llvm/IR/PassManager.h" +#include "llvm/Transforms/Instrumentation.h" + +namespace llvm { + +typedef IRBuilder BuilderTy; + +class BoundsChecking : public PassInfoMixin { + const TargetLibraryInfo *TLI; + ObjectSizeOffsetEvaluator *ObjSizeEval; + BuilderTy *Builder; + Instruction *Inst; + BasicBlock *TrapBB; + +public: + PreservedAnalyses run(Function &F, AnalysisManager &FAM); + +private: + BasicBlock *getTrapBB(); + void emitBranchToTrap(Value *Cmp = nullptr); + bool instrument(Value *Ptr, Value *InstVal, const DataLayout &DL); + + friend class BoundsCheckingLegacy; + bool check(Function &F, const TargetLibraryInfo *TLI); +}; + +} // End llvm namespace +#endif Index: lib/Passes/PassBuilder.cpp =================================================================== --- lib/Passes/PassBuilder.cpp +++ lib/Passes/PassBuilder.cpp @@ -67,6 +67,7 @@ #include "llvm/Transforms/IPO/StripDeadPrototypes.h" #include "llvm/Transforms/IPO/WholeProgramDevirt.h" #include "llvm/Transforms/InstCombine/InstCombine.h" +#include "llvm/Transforms/Instrumentation/BoundsChecking.h" #include "llvm/Transforms/InstrProfiling.h" #include "llvm/Transforms/PGOInstrumentation.h" #include "llvm/Transforms/SampleProfile.h" Index: lib/Passes/PassRegistry.def =================================================================== --- lib/Passes/PassRegistry.def +++ lib/Passes/PassRegistry.def @@ -125,6 +125,7 @@ FUNCTION_PASS("add-discriminators", AddDiscriminatorsPass()) FUNCTION_PASS("alignment-from-assumptions", AlignmentFromAssumptionsPass()) FUNCTION_PASS("bdce", BDCEPass()) +FUNCTION_PASS("bounds-checking", BoundsChecking()) FUNCTION_PASS("dce", DCEPass()) FUNCTION_PASS("dse", DSEPass()) FUNCTION_PASS("early-cse", EarlyCSEPass()) Index: lib/Transforms/Instrumentation/BoundsChecking.cpp =================================================================== --- lib/Transforms/Instrumentation/BoundsChecking.cpp +++ lib/Transforms/Instrumentation/BoundsChecking.cpp @@ -14,17 +14,15 @@ #include "llvm/Transforms/Instrumentation.h" #include "llvm/ADT/Statistic.h" -#include "llvm/Analysis/MemoryBuiltins.h" -#include "llvm/Analysis/TargetFolder.h" #include "llvm/Analysis/TargetLibraryInfo.h" #include "llvm/IR/DataLayout.h" -#include "llvm/IR/IRBuilder.h" #include "llvm/IR/InstIterator.h" #include "llvm/IR/Intrinsics.h" #include "llvm/Pass.h" #include "llvm/Support/CommandLine.h" #include "llvm/Support/Debug.h" #include "llvm/Support/raw_ostream.h" +#include "llvm/Transforms/Instrumentation/BoundsChecking.h" using namespace llvm; #define DEBUG_TYPE "bounds-checking" @@ -36,40 +34,6 @@ STATISTIC(ChecksSkipped, "Bounds checks skipped"); STATISTIC(ChecksUnable, "Bounds checks unable to add"); -typedef IRBuilder BuilderTy; - -namespace { - struct BoundsChecking : public FunctionPass { - static char ID; - - BoundsChecking() : FunctionPass(ID) { - initializeBoundsCheckingPass(*PassRegistry::getPassRegistry()); - } - - bool runOnFunction(Function &F) override; - - void getAnalysisUsage(AnalysisUsage &AU) const override { - AU.addRequired(); - } - - private: - const TargetLibraryInfo *TLI; - ObjectSizeOffsetEvaluator *ObjSizeEval; - BuilderTy *Builder; - Instruction *Inst; - BasicBlock *TrapBB; - - BasicBlock *getTrapBB(); - void emitBranchToTrap(Value *Cmp = nullptr); - bool instrument(Value *Ptr, Value *Val, const DataLayout &DL); - }; -} - -char BoundsChecking::ID = 0; -INITIALIZE_PASS(BoundsChecking, "bounds-checking", "Run-time bounds checking", - false, false) - - /// getTrapBB - create a basic block that traps. All overflowing conditions /// branch to this block. There's only one trap block per function. BasicBlock *BoundsChecking::getTrapBB() { @@ -163,9 +127,8 @@ return true; } -bool BoundsChecking::runOnFunction(Function &F) { +bool BoundsChecking::check(Function &F, const TargetLibraryInfo *TLI) { const DataLayout &DL = F.getParent()->getDataLayout(); - TLI = &getAnalysis().getTLI(); TrapBB = nullptr; BuilderTy TheBuilder(F.getContext(), TargetFolder(DL)); @@ -207,6 +170,54 @@ return MadeChange; } +PreservedAnalyses BoundsChecking::run(Function &F, + AnalysisManager &FAM) { + TargetLibraryInfo *TLI = &FAM.getResult(F); + + if (check(F, TLI)) + return PreservedAnalyses::none(); + + return PreservedAnalyses::all(); +} + +namespace llvm { +struct BoundsCheckingLegacy : public FunctionPass { + static char ID; + + BoundsCheckingLegacy() : FunctionPass(ID) { + initializeBoundsCheckingLegacyPass(*PassRegistry::getPassRegistry()); + } + + bool runOnFunction(Function &F) override { + const TargetLibraryInfo *TLI; + TLI = &getAnalysis().getTLI(); + return P->check(F, TLI); + } + + void getAnalysisUsage(AnalysisUsage &AU) const override { + AU.addRequired(); + } + + bool doInitialization(Module &M) override { + P.reset(new BoundsChecking()); + return false; + } + + bool doFinalization(Module &M) override { + P.reset(); + return false; + } + +private: + std::unique_ptr P; +}; +} + +char BoundsCheckingLegacy::ID = 0; +INITIALIZE_PASS(BoundsCheckingLegacy, "bounds-checking", + "Run-time bounds checking", + false, false) + FunctionPass *llvm::createBoundsCheckingPass() { - return new BoundsChecking(); + return new BoundsCheckingLegacy(); } Index: lib/Transforms/Instrumentation/CMakeLists.txt =================================================================== --- lib/Transforms/Instrumentation/CMakeLists.txt +++ lib/Transforms/Instrumentation/CMakeLists.txt @@ -14,6 +14,7 @@ ADDITIONAL_HEADER_DIRS ${LLVM_MAIN_INCLUDE_DIR}/llvm/Transforms + ${LLVM_MAIN_INCLUDE_DIR}/llvm/Transforms/Instrumentation ) add_dependencies(LLVMInstrumentation intrinsics_gen) Index: lib/Transforms/Instrumentation/Instrumentation.cpp =================================================================== --- lib/Transforms/Instrumentation/Instrumentation.cpp +++ lib/Transforms/Instrumentation/Instrumentation.cpp @@ -58,7 +58,7 @@ void llvm::initializeInstrumentation(PassRegistry &Registry) { initializeAddressSanitizerPass(Registry); initializeAddressSanitizerModulePass(Registry); - initializeBoundsCheckingPass(Registry); + initializeBoundsCheckingLegacyPass(Registry); initializeGCOVProfilerLegacyPassPass(Registry); initializePGOInstrumentationGenLegacyPassPass(Registry); initializePGOInstrumentationUseLegacyPassPass(Registry); Index: test/Instrumentation/BoundsChecking/many-trap.ll =================================================================== --- test/Instrumentation/BoundsChecking/many-trap.ll +++ test/Instrumentation/BoundsChecking/many-trap.ll @@ -1,5 +1,7 @@ ; RUN: opt < %s -bounds-checking -S | FileCheck %s +; RUN: opt < %s -passes=bounds-checking -S | FileCheck %s ; RUN: opt < %s -bounds-checking -bounds-checking-single-trap -S | FileCheck -check-prefix=SINGLE %s +; RUN: opt < %s -passes=bounds-checking -bounds-checking-single-trap -S | FileCheck -check-prefix=SINGLE %s target datalayout = "e-p:64:64:64-i1:8:8-i8:8:8-i16:16:16-i32:32:32-i64:64:64-f32:32:32-f64:64:64-v64:64:64-v128:128:128-a0:0:64-s0:64:64-f80:128:128-n8:16:32:64-S128" ; CHECK: @f1 Index: test/Instrumentation/BoundsChecking/phi.ll =================================================================== --- test/Instrumentation/BoundsChecking/phi.ll +++ test/Instrumentation/BoundsChecking/phi.ll @@ -1,4 +1,5 @@ ; RUN: opt < %s -bounds-checking -S | FileCheck %s +; RUN: opt < %s -passes=bounds-checking -S | FileCheck %s target datalayout = "e-p:64:64:64-p1:16:16:16-i1:8:8-i8:8:8-i16:16:16-i32:32:32-i64:64:64-f32:32:32-f64:64:64-v64:64:64-v128:128:128-a0:0:64-s0:64:64-f80:128:128-n8:16:32:64-S128" @global = private unnamed_addr constant [10 x i8] c"ola\00mundo\00", align 1 Index: test/Instrumentation/BoundsChecking/simple-32.ll =================================================================== --- test/Instrumentation/BoundsChecking/simple-32.ll +++ test/Instrumentation/BoundsChecking/simple-32.ll @@ -1,4 +1,5 @@ ; RUN: opt < %s -bounds-checking -S | FileCheck %s +; RUN: opt < %s -passes=bounds-checking -S | FileCheck %s target datalayout = "e-p:32:32:32-i1:8:8-i8:8:8-i16:16:16-i32:32:32-i64:32:64-f32:32:32-f64:32:64-v64:64:64-v128:128:128-a0:0:64-f80:32:32-n8:16:32-S128" Index: test/Instrumentation/BoundsChecking/simple.ll =================================================================== --- test/Instrumentation/BoundsChecking/simple.ll +++ test/Instrumentation/BoundsChecking/simple.ll @@ -1,4 +1,5 @@ ; RUN: opt < %s -bounds-checking -S | FileCheck %s +; RUN: opt < %s -passes=bounds-checking -S | FileCheck %s target datalayout = "e-p:64:64:64-p1:16:16:16-i1:8:8-i8:8:8-i16:16:16-i32:32:32-i64:64:64-f32:32:32-f64:64:64-v64:64:64-v128:128:128-a0:0:64-s0:64:64-f80:128:128-n8:16:32:64-S128" @.str = private constant [8 x i8] c"abcdefg\00" ; <[8 x i8]*>