diff options
Diffstat (limited to 'unittests/Transforms')
-rw-r--r-- | unittests/Transforms/DebugIR/CMakeLists.txt | 2 | ||||
-rw-r--r-- | unittests/Transforms/DebugIR/DebugIR.cpp | 22 | ||||
-rw-r--r-- | unittests/Transforms/Utils/ASanStackFrameLayoutTest.cpp | 102 | ||||
-rw-r--r-- | unittests/Transforms/Utils/CMakeLists.txt | 3 | ||||
-rw-r--r-- | unittests/Transforms/Utils/Cloning.cpp | 235 | ||||
-rw-r--r-- | unittests/Transforms/Utils/IntegerDivision.cpp | 122 | ||||
-rw-r--r-- | unittests/Transforms/Utils/SpecialCaseList.cpp | 23 |
7 files changed, 486 insertions, 23 deletions
diff --git a/unittests/Transforms/DebugIR/CMakeLists.txt b/unittests/Transforms/DebugIR/CMakeLists.txt index 4b47193..88734d2 100644 --- a/unittests/Transforms/DebugIR/CMakeLists.txt +++ b/unittests/Transforms/DebugIR/CMakeLists.txt @@ -1,5 +1,7 @@ set(LLVM_LINK_COMPONENTS + Core Instrumentation + Support ) add_llvm_unittest(DebugIRTests diff --git a/unittests/Transforms/DebugIR/DebugIR.cpp b/unittests/Transforms/DebugIR/DebugIR.cpp index 7d213fd..9b89c15 100644 --- a/unittests/Transforms/DebugIR/DebugIR.cpp +++ b/unittests/Transforms/DebugIR/DebugIR.cpp @@ -13,17 +13,16 @@ //===----------------------------------------------------------------------===// #include "llvm/ADT/Triple.h" +#include "../lib/Transforms/Instrumentation/DebugIR.h" #include "llvm/Config/config.h" -#include "llvm/DebugInfo.h" -#include "llvm/DIBuilder.h" +#include "llvm/IR/DIBuilder.h" +#include "llvm/IR/DebugInfo.h" #include "llvm/IR/Module.h" -#include "llvm/Support/Host.h" #include "llvm/Support/FileSystem.h" +#include "llvm/Support/Host.h" #include "llvm/Support/Path.h" #include "llvm/Transforms/Instrumentation.h" -#include "../lib/Transforms/Instrumentation/DebugIR.h" - // These tests do not depend on MCJIT, but we use the TrivialModuleBuilder // helper class to construct some trivial Modules. #include "../unittests/ExecutionEngine/MCJIT/MCJITTestBase.h" @@ -56,9 +55,10 @@ void insertCUDescriptor(Module *M, StringRef File, StringRef Dir, /// Attempts to remove file at Path and returns true if it existed, or false if /// it did not. bool removeIfExists(StringRef Path) { - bool existed = false; - sys::fs::remove(Path, existed); - return existed; + // This is an approximation, on error we don't know in general if the file + // existed or not. + llvm::error_code EC = sys::fs::remove(Path, false); + return EC != llvm::errc::no_such_file_or_directory; } char * current_dir() { @@ -90,8 +90,8 @@ protected: LLVMContext Context; char *cwd; - OwningPtr<Module> M; - OwningPtr<DebugIR> D; + std::unique_ptr<Module> M; + std::unique_ptr<DebugIR> D; }; // Test empty named Module that is not supposed to be output to disk. @@ -278,7 +278,7 @@ TEST_F(TestDebugIR, ExistingMetadataRetained) { // verify DebugIR did not generate a file ASSERT_FALSE(removeIfExists(Path)) << "Unexpected file " << Path; - DICompileUnit CU(*Finder.compile_unit_begin()); + DICompileUnit CU(*Finder.compile_units().begin()); // Verify original CU information is retained ASSERT_EQ(Filename, CU.getFilename()); diff --git a/unittests/Transforms/Utils/ASanStackFrameLayoutTest.cpp b/unittests/Transforms/Utils/ASanStackFrameLayoutTest.cpp new file mode 100644 index 0000000..0d3a239 --- /dev/null +++ b/unittests/Transforms/Utils/ASanStackFrameLayoutTest.cpp @@ -0,0 +1,102 @@ +//===- ASanStackFrameLayoutTest.cpp - Tests for ComputeASanStackFrameLayout===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +#include "llvm/Transforms/Utils/ASanStackFrameLayout.h" +#include "llvm/ADT/ArrayRef.h" +#include "gtest/gtest.h" +#include <sstream> + +using namespace llvm; + +static std::string +ShadowBytesToString(ArrayRef<uint8_t> ShadowBytes) { + std::ostringstream os; + for (size_t i = 0, n = ShadowBytes.size(); i < n; i++) { + switch (ShadowBytes[i]) { + case kAsanStackLeftRedzoneMagic: os << "L"; break; + case kAsanStackRightRedzoneMagic: os << "R"; break; + case kAsanStackMidRedzoneMagic: os << "M"; break; + default: os << (unsigned)ShadowBytes[i]; + } + } + return os.str(); +} + +static void TestLayout(SmallVector<ASanStackVariableDescription, 10> Vars, + size_t Granularity, size_t MinHeaderSize, + const std::string &ExpectedDescr, + const std::string &ExpectedShadow) { + ASanStackFrameLayout L; + ComputeASanStackFrameLayout(Vars, Granularity, MinHeaderSize, &L); + EXPECT_EQ(ExpectedDescr, L.DescriptionString); + EXPECT_EQ(ExpectedShadow, ShadowBytesToString(L.ShadowBytes)); +} + +TEST(ASanStackFrameLayout, Test) { +#define VEC1(a) SmallVector<ASanStackVariableDescription, 10>(1, a) +#define VEC(a) \ + SmallVector<ASanStackVariableDescription, 10>(a, a + sizeof(a) / sizeof(a[0])) + +#define VAR(name, size, alignment) \ + ASanStackVariableDescription name##size##_##alignment = { \ + #name #size "_" #alignment, \ + size, \ + alignment, \ + 0, \ + 0 \ + } + + VAR(a, 1, 1); + VAR(p, 1, 32); + VAR(p, 1, 256); + VAR(a, 2, 1); + VAR(a, 3, 1); + VAR(a, 4, 1); + VAR(a, 7, 1); + VAR(a, 8, 1); + VAR(a, 9, 1); + VAR(a, 16, 1); + VAR(a, 41, 1); + VAR(a, 105, 1); + + TestLayout(VEC1(a1_1), 8, 16, "1 16 1 4 a1_1", "LL1R"); + TestLayout(VEC1(a1_1), 64, 64, "1 64 1 4 a1_1", "L1"); + TestLayout(VEC1(p1_32), 8, 32, "1 32 1 5 p1_32", "LLLL1RRR"); + TestLayout(VEC1(p1_32), 8, 64, "1 64 1 5 p1_32", "LLLLLLLL1RRRRRRR"); + + TestLayout(VEC1(a1_1), 8, 32, "1 32 1 4 a1_1", "LLLL1RRR"); + TestLayout(VEC1(a2_1), 8, 32, "1 32 2 4 a2_1", "LLLL2RRR"); + TestLayout(VEC1(a3_1), 8, 32, "1 32 3 4 a3_1", "LLLL3RRR"); + TestLayout(VEC1(a4_1), 8, 32, "1 32 4 4 a4_1", "LLLL4RRR"); + TestLayout(VEC1(a7_1), 8, 32, "1 32 7 4 a7_1", "LLLL7RRR"); + TestLayout(VEC1(a8_1), 8, 32, "1 32 8 4 a8_1", "LLLL0RRR"); + TestLayout(VEC1(a9_1), 8, 32, "1 32 9 4 a9_1", "LLLL01RR"); + TestLayout(VEC1(a16_1), 8, 32, "1 32 16 5 a16_1", "LLLL00RR"); + TestLayout(VEC1(p1_256), 8, 32, "1 256 1 6 p1_256", + "LLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLL1RRR"); + TestLayout(VEC1(a41_1), 8, 32, "1 32 41 5 a41_1", "LLLL000001RRRRRR"); + TestLayout(VEC1(a105_1), 8, 32, "1 32 105 6 a105_1", + "LLLL00000000000001RRRRRR"); + + { + ASanStackVariableDescription t[] = {a1_1, p1_256}; + TestLayout(VEC(t), 8, 32, + "2 256 1 6 p1_256 272 1 4 a1_1", + "LLLLLLLL" "LLLLLLLL" "LLLLLLLL" "LLLLLLLL" "1M1R"); + } + + { + ASanStackVariableDescription t[] = {a1_1, a16_1, a41_1}; + TestLayout(VEC(t), 8, 32, + "3 32 1 4 a1_1 48 16 5 a16_1 80 41 5 a41_1", + "LLLL" "1M00" "MM00" "0001" "RRRR"); + } +#undef VEC1 +#undef VEC +#undef VAR +} diff --git a/unittests/Transforms/Utils/CMakeLists.txt b/unittests/Transforms/Utils/CMakeLists.txt index 0656390..60447bb 100644 --- a/unittests/Transforms/Utils/CMakeLists.txt +++ b/unittests/Transforms/Utils/CMakeLists.txt @@ -1,8 +1,11 @@ set(LLVM_LINK_COMPONENTS + Core + Support TransformUtils ) add_llvm_unittest(UtilsTests + ASanStackFrameLayoutTest.cpp Cloning.cpp IntegerDivision.cpp Local.cpp diff --git a/unittests/Transforms/Utils/Cloning.cpp b/unittests/Transforms/Utils/Cloning.cpp index e19ae5b..fb27dc1 100644 --- a/unittests/Transforms/Utils/Cloning.cpp +++ b/unittests/Transforms/Utils/Cloning.cpp @@ -7,15 +7,22 @@ // //===----------------------------------------------------------------------===// +#include "llvm/Transforms/Utils/Cloning.h" +#include "llvm/ADT/ArrayRef.h" #include "llvm/ADT/STLExtras.h" #include "llvm/ADT/SmallPtrSet.h" #include "llvm/IR/Argument.h" #include "llvm/IR/Constant.h" +#include "llvm/IR/DebugInfo.h" +#include "llvm/IR/DIBuilder.h" #include "llvm/IR/Function.h" +#include "llvm/IR/IRBuilder.h" +#include "llvm/IR/InstIterator.h" #include "llvm/IR/Instructions.h" +#include "llvm/IR/IntrinsicInst.h" #include "llvm/IR/IRBuilder.h" +#include "llvm/IR/Module.h" #include "llvm/IR/LLVMContext.h" -#include "llvm/Transforms/Utils/Cloning.h" #include "gtest/gtest.h" using namespace llvm; @@ -173,4 +180,230 @@ TEST_F(CloneInstruction, Attributes) { delete F2; } +TEST_F(CloneInstruction, CallingConvention) { + Type *ArgTy1[] = { Type::getInt32PtrTy(context) }; + FunctionType *FT1 = FunctionType::get(Type::getVoidTy(context), ArgTy1, false); + + Function *F1 = Function::Create(FT1, Function::ExternalLinkage); + F1->setCallingConv(CallingConv::Cold); + BasicBlock *BB = BasicBlock::Create(context, "", F1); + IRBuilder<> Builder(BB); + Builder.CreateRetVoid(); + + Function *F2 = Function::Create(FT1, Function::ExternalLinkage); + + SmallVector<ReturnInst*, 4> Returns; + ValueToValueMapTy VMap; + VMap[F1->arg_begin()] = F2->arg_begin(); + + CloneFunctionInto(F2, F1, VMap, false, Returns); + EXPECT_EQ(CallingConv::Cold, F2->getCallingConv()); + + delete F1; + delete F2; +} + +class CloneFunc : public ::testing::Test { +protected: + virtual void SetUp() { + SetupModule(); + CreateOldFunc(); + CreateNewFunc(); + SetupFinder(); + } + + virtual void TearDown() { + delete Finder; + } + + void SetupModule() { + M = new Module("", C); + } + + void CreateOldFunc() { + FunctionType* FuncType = FunctionType::get(Type::getVoidTy(C), false); + OldFunc = Function::Create(FuncType, GlobalValue::PrivateLinkage, "f", M); + CreateOldFunctionBodyAndDI(); + } + + void CreateOldFunctionBodyAndDI() { + DIBuilder DBuilder(*M); + IRBuilder<> IBuilder(C); + + // Function DI + DIFile File = DBuilder.createFile("filename.c", "/file/dir/"); + DIArray ParamTypes = DBuilder.getOrCreateArray(ArrayRef<Value*>()); + DICompositeType FuncType = DBuilder.createSubroutineType(File, ParamTypes); + DICompileUnit CU = DBuilder.createCompileUnit(dwarf::DW_LANG_C99, + "filename.c", "/file/dir", "CloneFunc", false, "", 0); + + DISubprogram Subprogram = DBuilder.createFunction(CU, "f", "f", File, 4, + FuncType, true, true, 3, 0, false, OldFunc); + + // Function body + BasicBlock* Entry = BasicBlock::Create(C, "", OldFunc); + IBuilder.SetInsertPoint(Entry); + DebugLoc Loc = DebugLoc::get(3, 2, Subprogram); + IBuilder.SetCurrentDebugLocation(Loc); + AllocaInst* Alloca = IBuilder.CreateAlloca(IntegerType::getInt32Ty(C)); + IBuilder.SetCurrentDebugLocation(DebugLoc::get(4, 2, Subprogram)); + Value* AllocaContent = IBuilder.getInt32(1); + Instruction* Store = IBuilder.CreateStore(AllocaContent, Alloca); + IBuilder.SetCurrentDebugLocation(DebugLoc::get(5, 2, Subprogram)); + Instruction* Terminator = IBuilder.CreateRetVoid(); + + // Create a local variable around the alloca + DIType IntType = DBuilder.createBasicType("int", 32, 0, + dwarf::DW_ATE_signed); + DIVariable Variable = DBuilder.createLocalVariable( + dwarf::DW_TAG_auto_variable, Subprogram, "x", File, 5, IntType, true); + DBuilder.insertDeclare(Alloca, Variable, Store); + DBuilder.insertDbgValueIntrinsic(AllocaContent, 0, Variable, Terminator); + // Finalize the debug info + DBuilder.finalize(); + + + // Create another, empty, compile unit + DIBuilder DBuilder2(*M); + DBuilder2.createCompileUnit(dwarf::DW_LANG_C99, + "extra.c", "/file/dir", "CloneFunc", false, "", 0); + DBuilder2.finalize(); + } + + void CreateNewFunc() { + ValueToValueMapTy VMap; + NewFunc = CloneFunction(OldFunc, VMap, true, NULL); + M->getFunctionList().push_back(NewFunc); + } + + void SetupFinder() { + Finder = new DebugInfoFinder(); + Finder->processModule(*M); + } + + LLVMContext C; + Function* OldFunc; + Function* NewFunc; + Module* M; + DebugInfoFinder* Finder; +}; + +// Test that a new, distinct function was created. +TEST_F(CloneFunc, NewFunctionCreated) { + EXPECT_NE(OldFunc, NewFunc); +} + +// Test that a new subprogram entry was added and is pointing to the new +// function, while the original subprogram still points to the old one. +TEST_F(CloneFunc, Subprogram) { + unsigned SubprogramCount = Finder->subprogram_count(); + EXPECT_EQ(2U, SubprogramCount); + + auto Iter = Finder->subprograms().begin(); + DISubprogram Sub1(*Iter); + EXPECT_TRUE(Sub1.Verify()); + Iter++; + DISubprogram Sub2(*Iter); + EXPECT_TRUE(Sub2.Verify()); + + EXPECT_TRUE((Sub1.getFunction() == OldFunc && Sub2.getFunction() == NewFunc) + || (Sub1.getFunction() == NewFunc && Sub2.getFunction() == OldFunc)); +} + +// Test that the new subprogram entry was not added to the CU which doesn't +// contain the old subprogram entry. +TEST_F(CloneFunc, SubprogramInRightCU) { + EXPECT_EQ(2U, Finder->compile_unit_count()); + + auto Iter = Finder->compile_units().begin(); + DICompileUnit CU1(*Iter); + EXPECT_TRUE(CU1.Verify()); + Iter++; + DICompileUnit CU2(*Iter); + EXPECT_TRUE(CU2.Verify()); + EXPECT_TRUE(CU1.getSubprograms().getNumElements() == 0 + || CU2.getSubprograms().getNumElements() == 0); +} + +// Test that instructions in the old function still belong to it in the +// metadata, while instruction in the new function belong to the new one. +TEST_F(CloneFunc, InstructionOwnership) { + inst_iterator OldIter = inst_begin(OldFunc); + inst_iterator OldEnd = inst_end(OldFunc); + inst_iterator NewIter = inst_begin(NewFunc); + inst_iterator NewEnd = inst_end(NewFunc); + while (OldIter != OldEnd && NewIter != NewEnd) { + Instruction& OldI = *OldIter; + Instruction& NewI = *NewIter; + EXPECT_NE(&OldI, &NewI); + + EXPECT_EQ(OldI.hasMetadata(), NewI.hasMetadata()); + if (OldI.hasMetadata()) { + const DebugLoc& OldDL = OldI.getDebugLoc(); + const DebugLoc& NewDL = NewI.getDebugLoc(); + + // Verify that the debug location data is the same + EXPECT_EQ(OldDL.getLine(), NewDL.getLine()); + EXPECT_EQ(OldDL.getCol(), NewDL.getCol()); + + // But that they belong to different functions + DISubprogram OldSubprogram(OldDL.getScope(C)); + DISubprogram NewSubprogram(NewDL.getScope(C)); + EXPECT_TRUE(OldSubprogram.Verify()); + EXPECT_TRUE(NewSubprogram.Verify()); + EXPECT_EQ(OldFunc, OldSubprogram.getFunction()); + EXPECT_EQ(NewFunc, NewSubprogram.getFunction()); + } + + ++OldIter; + ++NewIter; + } + EXPECT_EQ(OldEnd, OldIter); + EXPECT_EQ(NewEnd, NewIter); +} + +// Test that the arguments for debug intrinsics in the new function were +// properly cloned +TEST_F(CloneFunc, DebugIntrinsics) { + inst_iterator OldIter = inst_begin(OldFunc); + inst_iterator OldEnd = inst_end(OldFunc); + inst_iterator NewIter = inst_begin(NewFunc); + inst_iterator NewEnd = inst_end(NewFunc); + while (OldIter != OldEnd && NewIter != NewEnd) { + Instruction& OldI = *OldIter; + Instruction& NewI = *NewIter; + if (DbgDeclareInst* OldIntrin = dyn_cast<DbgDeclareInst>(&OldI)) { + DbgDeclareInst* NewIntrin = dyn_cast<DbgDeclareInst>(&NewI); + EXPECT_TRUE(NewIntrin); + + // Old address must belong to the old function + EXPECT_EQ(OldFunc, cast<AllocaInst>(OldIntrin->getAddress())-> + getParent()->getParent()); + // New address must belong to the new function + EXPECT_EQ(NewFunc, cast<AllocaInst>(NewIntrin->getAddress())-> + getParent()->getParent()); + + // Old variable must belong to the old function + EXPECT_EQ(OldFunc, DISubprogram(DIVariable(OldIntrin->getVariable()) + .getContext()).getFunction()); + // New variable must belong to the New function + EXPECT_EQ(NewFunc, DISubprogram(DIVariable(NewIntrin->getVariable()) + .getContext()).getFunction()); + } else if (DbgValueInst* OldIntrin = dyn_cast<DbgValueInst>(&OldI)) { + DbgValueInst* NewIntrin = dyn_cast<DbgValueInst>(&NewI); + EXPECT_TRUE(NewIntrin); + + // Old variable must belong to the old function + EXPECT_EQ(OldFunc, DISubprogram(DIVariable(OldIntrin->getVariable()) + .getContext()).getFunction()); + // New variable must belong to the New function + EXPECT_EQ(NewFunc, DISubprogram(DIVariable(NewIntrin->getVariable()) + .getContext()).getFunction()); + } + + ++OldIter; + ++NewIter; + } +} + } diff --git a/unittests/Transforms/Utils/IntegerDivision.cpp b/unittests/Transforms/Utils/IntegerDivision.cpp index 44c2328..f7318a2 100644 --- a/unittests/Transforms/Utils/IntegerDivision.cpp +++ b/unittests/Transforms/Utils/IntegerDivision.cpp @@ -19,6 +19,7 @@ using namespace llvm; namespace { + TEST(IntegerDivision, SDiv) { LLVMContext &C(getGlobalContext()); Module M("test division", C); @@ -139,4 +140,125 @@ TEST(IntegerDivision, URem) { EXPECT_TRUE(Remainder && Remainder->getOpcode() == Instruction::Sub); } + +TEST(IntegerDivision, SDiv64) { + LLVMContext &C(getGlobalContext()); + Module M("test division", C); + IRBuilder<> Builder(C); + + SmallVector<Type*, 2> ArgTys(2, Builder.getInt64Ty()); + Function *F = Function::Create(FunctionType::get(Builder.getInt64Ty(), + ArgTys, false), + GlobalValue::ExternalLinkage, "F", &M); + assert(F->getArgumentList().size() == 2); + + BasicBlock *BB = BasicBlock::Create(C, "", F); + Builder.SetInsertPoint(BB); + + Function::arg_iterator AI = F->arg_begin(); + Value *A = AI++; + Value *B = AI++; + + Value *Div = Builder.CreateSDiv(A, B); + EXPECT_TRUE(BB->front().getOpcode() == Instruction::SDiv); + + Value *Ret = Builder.CreateRet(Div); + + expandDivision(cast<BinaryOperator>(Div)); + EXPECT_TRUE(BB->front().getOpcode() == Instruction::AShr); + + Instruction* Quotient = dyn_cast<Instruction>(cast<User>(Ret)->getOperand(0)); + EXPECT_TRUE(Quotient && Quotient->getOpcode() == Instruction::Sub); +} + +TEST(IntegerDivision, UDiv64) { + LLVMContext &C(getGlobalContext()); + Module M("test division", C); + IRBuilder<> Builder(C); + + SmallVector<Type*, 2> ArgTys(2, Builder.getInt64Ty()); + Function *F = Function::Create(FunctionType::get(Builder.getInt64Ty(), + ArgTys, false), + GlobalValue::ExternalLinkage, "F", &M); + assert(F->getArgumentList().size() == 2); + + BasicBlock *BB = BasicBlock::Create(C, "", F); + Builder.SetInsertPoint(BB); + + Function::arg_iterator AI = F->arg_begin(); + Value *A = AI++; + Value *B = AI++; + + Value *Div = Builder.CreateUDiv(A, B); + EXPECT_TRUE(BB->front().getOpcode() == Instruction::UDiv); + + Value *Ret = Builder.CreateRet(Div); + + expandDivision(cast<BinaryOperator>(Div)); + EXPECT_TRUE(BB->front().getOpcode() == Instruction::ICmp); + + Instruction* Quotient = dyn_cast<Instruction>(cast<User>(Ret)->getOperand(0)); + EXPECT_TRUE(Quotient && Quotient->getOpcode() == Instruction::PHI); +} + +TEST(IntegerDivision, SRem64) { + LLVMContext &C(getGlobalContext()); + Module M("test remainder", C); + IRBuilder<> Builder(C); + + SmallVector<Type*, 2> ArgTys(2, Builder.getInt64Ty()); + Function *F = Function::Create(FunctionType::get(Builder.getInt64Ty(), + ArgTys, false), + GlobalValue::ExternalLinkage, "F", &M); + assert(F->getArgumentList().size() == 2); + + BasicBlock *BB = BasicBlock::Create(C, "", F); + Builder.SetInsertPoint(BB); + + Function::arg_iterator AI = F->arg_begin(); + Value *A = AI++; + Value *B = AI++; + + Value *Rem = Builder.CreateSRem(A, B); + EXPECT_TRUE(BB->front().getOpcode() == Instruction::SRem); + + Value *Ret = Builder.CreateRet(Rem); + + expandRemainder(cast<BinaryOperator>(Rem)); + EXPECT_TRUE(BB->front().getOpcode() == Instruction::AShr); + + Instruction* Remainder = dyn_cast<Instruction>(cast<User>(Ret)->getOperand(0)); + EXPECT_TRUE(Remainder && Remainder->getOpcode() == Instruction::Sub); +} + +TEST(IntegerDivision, URem64) { + LLVMContext &C(getGlobalContext()); + Module M("test remainder", C); + IRBuilder<> Builder(C); + + SmallVector<Type*, 2> ArgTys(2, Builder.getInt64Ty()); + Function *F = Function::Create(FunctionType::get(Builder.getInt64Ty(), + ArgTys, false), + GlobalValue::ExternalLinkage, "F", &M); + assert(F->getArgumentList().size() == 2); + + BasicBlock *BB = BasicBlock::Create(C, "", F); + Builder.SetInsertPoint(BB); + + Function::arg_iterator AI = F->arg_begin(); + Value *A = AI++; + Value *B = AI++; + + Value *Rem = Builder.CreateURem(A, B); + EXPECT_TRUE(BB->front().getOpcode() == Instruction::URem); + + Value *Ret = Builder.CreateRet(Rem); + + expandRemainder(cast<BinaryOperator>(Rem)); + EXPECT_TRUE(BB->front().getOpcode() == Instruction::ICmp); + + Instruction* Remainder = dyn_cast<Instruction>(cast<User>(Ret)->getOperand(0)); + EXPECT_TRUE(Remainder && Remainder->getOpcode() == Instruction::Sub); +} + } diff --git a/unittests/Transforms/Utils/SpecialCaseList.cpp b/unittests/Transforms/Utils/SpecialCaseList.cpp index 07ac908..748834f 100644 --- a/unittests/Transforms/Utils/SpecialCaseList.cpp +++ b/unittests/Transforms/Utils/SpecialCaseList.cpp @@ -40,7 +40,7 @@ protected: } SpecialCaseList *makeSpecialCaseList(StringRef List, std::string &Error) { - OwningPtr<MemoryBuffer> MB(MemoryBuffer::getMemBuffer(List)); + std::unique_ptr<MemoryBuffer> MB(MemoryBuffer::getMemBuffer(List)); return SpecialCaseList::create(MB.get(), Error); } @@ -60,9 +60,10 @@ TEST_F(SpecialCaseListTest, ModuleIsIn) { Function *F = makeFunction("foo", M); GlobalVariable *GV = makeGlobal("bar", "t", M); - OwningPtr<SpecialCaseList> SCL(makeSpecialCaseList("# This is a comment.\n" - "\n" - "src:hello\n")); + std::unique_ptr<SpecialCaseList> SCL( + makeSpecialCaseList("# This is a comment.\n" + "\n" + "src:hello\n")); EXPECT_TRUE(SCL->isIn(M)); EXPECT_TRUE(SCL->isIn(*F)); EXPECT_TRUE(SCL->isIn(*GV)); @@ -83,7 +84,7 @@ TEST_F(SpecialCaseListTest, FunctionIsIn) { Function *Foo = makeFunction("foo", M); Function *Bar = makeFunction("bar", M); - OwningPtr<SpecialCaseList> SCL(makeSpecialCaseList("fun:foo\n")); + std::unique_ptr<SpecialCaseList> SCL(makeSpecialCaseList("fun:foo\n")); EXPECT_TRUE(SCL->isIn(*Foo)); EXPECT_FALSE(SCL->isIn(*Bar)); @@ -107,7 +108,7 @@ TEST_F(SpecialCaseListTest, GlobalIsIn) { GlobalVariable *Foo = makeGlobal("foo", "t1", M); GlobalVariable *Bar = makeGlobal("bar", "t2", M); - OwningPtr<SpecialCaseList> SCL(makeSpecialCaseList("global:foo\n")); + std::unique_ptr<SpecialCaseList> SCL(makeSpecialCaseList("global:foo\n")); EXPECT_TRUE(SCL->isIn(*Foo)); EXPECT_FALSE(SCL->isIn(*Bar)); EXPECT_FALSE(SCL->isIn(*Foo, "init")); @@ -157,7 +158,7 @@ TEST_F(SpecialCaseListTest, AliasIsIn) { GlobalAlias *FooAlias = makeAlias("fooalias", Foo); GlobalAlias *BarAlias = makeAlias("baralias", Bar); - OwningPtr<SpecialCaseList> SCL(makeSpecialCaseList("fun:foo\n")); + std::unique_ptr<SpecialCaseList> SCL(makeSpecialCaseList("fun:foo\n")); EXPECT_FALSE(SCL->isIn(*FooAlias)); EXPECT_FALSE(SCL->isIn(*BarAlias)); @@ -193,9 +194,9 @@ TEST_F(SpecialCaseListTest, Substring) { GlobalAlias *GA1 = makeAlias("buffoonery", F); GlobalAlias *GA2 = makeAlias("foobar", GV); - OwningPtr<SpecialCaseList> SCL(makeSpecialCaseList("src:hello\n" - "fun:foo\n" - "global:bar\n")); + std::unique_ptr<SpecialCaseList> SCL(makeSpecialCaseList("src:hello\n" + "fun:foo\n" + "global:bar\n")); EXPECT_FALSE(SCL->isIn(M)); EXPECT_FALSE(SCL->isIn(*F)); EXPECT_FALSE(SCL->isIn(*GV)); @@ -224,7 +225,7 @@ TEST_F(SpecialCaseListTest, InvalidSpecialCaseList) { } TEST_F(SpecialCaseListTest, EmptySpecialCaseList) { - OwningPtr<SpecialCaseList> SCL(makeSpecialCaseList("")); + std::unique_ptr<SpecialCaseList> SCL(makeSpecialCaseList("")); Module M("foo", Ctx); EXPECT_FALSE(SCL->isIn(M)); } |