diff options
Diffstat (limited to 'unittests')
-rw-r--r-- | unittests/ADT/APFloatTest.cpp | 22 | ||||
-rw-r--r-- | unittests/ADT/DeltaAlgorithmTest.cpp | 4 | ||||
-rw-r--r-- | unittests/ADT/StringRefTest.cpp | 18 | ||||
-rw-r--r-- | unittests/ExecutionEngine/JIT/JITTest.cpp | 166 | ||||
-rw-r--r-- | unittests/ExecutionEngine/JIT/Makefile | 2 | ||||
-rw-r--r-- | unittests/Support/LeakDetectorTest.cpp | 29 | ||||
-rw-r--r-- | unittests/VMCore/DerivedTypesTest.cpp | 31 | ||||
-rw-r--r-- | unittests/VMCore/MetadataTest.cpp | 31 |
8 files changed, 271 insertions, 32 deletions
diff --git a/unittests/ADT/APFloatTest.cpp b/unittests/ADT/APFloatTest.cpp index 92f020b..76cdafc 100644 --- a/unittests/ADT/APFloatTest.cpp +++ b/unittests/ADT/APFloatTest.cpp @@ -8,10 +8,12 @@ //===----------------------------------------------------------------------===// #include <ostream> +#include <string> #include "llvm/Support/raw_ostream.h" #include "gtest/gtest.h" #include "llvm/ADT/APFloat.h" #include "llvm/ADT/SmallString.h" +#include "llvm/ADT/SmallVector.h" using namespace llvm; @@ -21,6 +23,13 @@ static double convertToDoubleFromString(const char *Str) { return F.convertToDouble(); } +static std::string convertToString(double d, unsigned Prec, unsigned Pad) { + llvm::SmallVector<char, 100> Buffer; + llvm::APFloat F(d); + F.toString(Buffer, Prec, Pad); + return std::string(Buffer.data(), Buffer.size()); +} + namespace { TEST(APFloatTest, Zero) { @@ -313,6 +322,19 @@ TEST(APFloatTest, fromHexadecimalString) { EXPECT_EQ(2.71828, convertToDoubleFromString("2.71828")); } +TEST(APFloatTest, toString) { + ASSERT_EQ("10", convertToString(10.0, 6, 3)); + ASSERT_EQ("1.0E+1", convertToString(10.0, 6, 0)); + ASSERT_EQ("10100", convertToString(1.01E+4, 5, 2)); + ASSERT_EQ("1.01E+4", convertToString(1.01E+4, 4, 2)); + ASSERT_EQ("1.01E+4", convertToString(1.01E+4, 5, 1)); + ASSERT_EQ("0.0101", convertToString(1.01E-2, 5, 2)); + ASSERT_EQ("0.0101", convertToString(1.01E-2, 4, 2)); + ASSERT_EQ("1.01E-2", convertToString(1.01E-2, 5, 1)); + ASSERT_EQ("0.7853981633974483", convertToString(0.78539816339744830961, 0, 3)); + ASSERT_EQ("4.940656458412465E-324", convertToString(4.9406564584124654e-324, 0, 3)); +} + #ifdef GTEST_HAS_DEATH_TEST TEST(APFloatTest, SemanticsDeath) { EXPECT_DEATH(APFloat(APFloat::IEEEsingle, 0.0f).convertToDouble(), "Float semantics are not IEEEdouble"); diff --git a/unittests/ADT/DeltaAlgorithmTest.cpp b/unittests/ADT/DeltaAlgorithmTest.cpp index 3628922..a1884cd 100644 --- a/unittests/ADT/DeltaAlgorithmTest.cpp +++ b/unittests/ADT/DeltaAlgorithmTest.cpp @@ -13,6 +13,8 @@ #include <cstdarg> using namespace llvm; +namespace std { + std::ostream &operator<<(std::ostream &OS, const std::set<unsigned> &S) { OS << "{"; @@ -26,6 +28,8 @@ std::ostream &operator<<(std::ostream &OS, return OS; } +} + namespace { class FixedDeltaAlgorithm : public DeltaAlgorithm { diff --git a/unittests/ADT/StringRefTest.cpp b/unittests/ADT/StringRefTest.cpp index dfa208a..b0dcb0a 100644 --- a/unittests/ADT/StringRefTest.cpp +++ b/unittests/ADT/StringRefTest.cpp @@ -13,7 +13,7 @@ #include "llvm/Support/raw_ostream.h" using namespace llvm; -namespace { +namespace llvm { std::ostream &operator<<(std::ostream &OS, const StringRef &S) { OS << S; @@ -26,6 +26,9 @@ std::ostream &operator<<(std::ostream &OS, return OS; } +} + +namespace { TEST(StringRefTest, Construction) { EXPECT_EQ("", StringRef()); EXPECT_EQ("hello", StringRef("hello")); @@ -198,6 +201,14 @@ TEST(StringRefTest, StartsWith) { EXPECT_FALSE(Str.startswith("hi")); } +TEST(StringRefTest, EndsWith) { + StringRef Str("hello"); + EXPECT_TRUE(Str.endswith("lo")); + EXPECT_FALSE(Str.endswith("helloworld")); + EXPECT_FALSE(Str.endswith("worldhello")); + EXPECT_FALSE(Str.endswith("so")); +} + TEST(StringRefTest, Find) { StringRef Str("hello"); EXPECT_EQ(2U, Str.find('l')); @@ -236,6 +247,11 @@ TEST(StringRefTest, Count) { EXPECT_EQ(0U, Str.count("zz")); } +TEST(StringRefTest, EditDistance) { + StringRef Str("hello"); + EXPECT_EQ(2U, Str.edit_distance("hill")); +} + TEST(StringRefTest, Misc) { std::string Storage; raw_string_ostream OS(Storage); diff --git a/unittests/ExecutionEngine/JIT/JITTest.cpp b/unittests/ExecutionEngine/JIT/JITTest.cpp index bbf3460..7f75afa 100644 --- a/unittests/ExecutionEngine/JIT/JITTest.cpp +++ b/unittests/ExecutionEngine/JIT/JITTest.cpp @@ -12,6 +12,7 @@ #include "llvm/ADT/SmallPtrSet.h" #include "llvm/Assembly/Parser.h" #include "llvm/BasicBlock.h" +#include "llvm/Bitcode/ReaderWriter.h" #include "llvm/Constant.h" #include "llvm/Constants.h" #include "llvm/DerivedTypes.h" @@ -24,6 +25,7 @@ #include "llvm/Module.h" #include "llvm/ModuleProvider.h" #include "llvm/Support/IRBuilder.h" +#include "llvm/Support/MemoryBuffer.h" #include "llvm/Support/SourceMgr.h" #include "llvm/Support/TypeBuilder.h" #include "llvm/Target/TargetSelect.h" @@ -177,6 +179,17 @@ public: } }; +bool LoadAssemblyInto(Module *M, const char *assembly) { + SMDiagnostic Error; + bool success = + NULL != ParseAssemblyString(assembly, M, Error, M->getContext()); + std::string errMsg; + raw_string_ostream os(errMsg); + Error.Print("", os); + EXPECT_TRUE(success) << os.str(); + return success; +} + class JITTest : public testing::Test { protected: virtual void SetUp() { @@ -192,12 +205,7 @@ class JITTest : public testing::Test { } void LoadAssembly(const char *assembly) { - SMDiagnostic Error; - bool success = NULL != ParseAssemblyString(assembly, M, Error, Context); - std::string errMsg; - raw_string_ostream os(errMsg); - Error.Print("", os); - ASSERT_TRUE(success) << os.str(); + LoadAssemblyInto(M, assembly); } LLVMContext Context; @@ -534,6 +542,41 @@ TEST_F(JITTest, FunctionPointersOutliveTheirCreator) { #endif } +// ARM doesn't have an implementation of replaceMachineCodeForFunction(), so +// recompileAndRelinkFunction doesn't work. +#if !defined(__arm__) +TEST_F(JITTest, FunctionIsRecompiledAndRelinked) { + Function *F = Function::Create(TypeBuilder<int(void), false>::get(Context), + GlobalValue::ExternalLinkage, "test", M); + BasicBlock *Entry = BasicBlock::Create(Context, "entry", F); + IRBuilder<> Builder(Entry); + Value *Val = ConstantInt::get(TypeBuilder<int, false>::get(Context), 1); + Builder.CreateRet(Val); + + TheJIT->DisableLazyCompilation(true); + // Compile the function once, and make sure it works. + int (*OrigFPtr)() = reinterpret_cast<int(*)()>( + (intptr_t)TheJIT->recompileAndRelinkFunction(F)); + EXPECT_EQ(1, OrigFPtr()); + + // Now change the function to return a different value. + Entry->eraseFromParent(); + BasicBlock *NewEntry = BasicBlock::Create(Context, "new_entry", F); + Builder.SetInsertPoint(NewEntry); + Val = ConstantInt::get(TypeBuilder<int, false>::get(Context), 2); + Builder.CreateRet(Val); + // Recompile it, which should produce a new function pointer _and_ update the + // old one. + int (*NewFPtr)() = reinterpret_cast<int(*)()>( + (intptr_t)TheJIT->recompileAndRelinkFunction(F)); + + EXPECT_EQ(2, NewFPtr()) + << "The new pointer should call the new version of the function"; + EXPECT_EQ(2, OrigFPtr()) + << "The old pointer's target should now jump to the new version"; +} +#endif // !defined(__arm__) + } // anonymous namespace // This variable is intentionally defined differently in the statically-compiled // program from the IR input to the JIT to assert that the JIT doesn't use its @@ -559,6 +602,117 @@ TEST_F(JITTest, AvailableExternallyGlobalIsntEmitted) { << " not 7 from the IR version."; } +} // anonymous namespace +// This function is intentionally defined differently in the statically-compiled +// program from the IR input to the JIT to assert that the JIT doesn't use its +// definition. +extern "C" int32_t JITTest_AvailableExternallyFunction() { + return 42; +} +namespace { + +TEST_F(JITTest, AvailableExternallyFunctionIsntCompiled) { + TheJIT->DisableLazyCompilation(true); + LoadAssembly("define available_externally i32 " + " @JITTest_AvailableExternallyFunction() { " + " ret i32 7 " + "} " + " " + "define i32 @func() { " + " %result = tail call i32 " + " @JITTest_AvailableExternallyFunction() " + " ret i32 %result " + "} "); + Function *funcIR = M->getFunction("func"); + + int32_t (*func)() = reinterpret_cast<int32_t(*)()>( + (intptr_t)TheJIT->getPointerToFunction(funcIR)); + EXPECT_EQ(42, func()) << "func should return 42 from the static version," + << " not 7 from the IR version."; +} + +// Converts the LLVM assembly to bitcode and returns it in a std::string. An +// empty string indicates an error. +std::string AssembleToBitcode(LLVMContext &Context, const char *Assembly) { + Module TempModule("TempModule", Context); + if (!LoadAssemblyInto(&TempModule, Assembly)) { + return ""; + } + + std::string Result; + raw_string_ostream OS(Result); + WriteBitcodeToFile(&TempModule, OS); + OS.flush(); + return Result; +} + +// Returns a newly-created ExecutionEngine that reads the bitcode in 'Bitcode' +// lazily. The associated ModuleProvider (owned by the ExecutionEngine) is +// returned in MP. Both will be NULL on an error. Bitcode must live at least +// as long as the ExecutionEngine. +ExecutionEngine *getJITFromBitcode( + LLVMContext &Context, const std::string &Bitcode, ModuleProvider *&MP) { + // c_str() is null-terminated like MemoryBuffer::getMemBuffer requires. + MemoryBuffer *BitcodeBuffer = + MemoryBuffer::getMemBuffer(Bitcode.c_str(), + Bitcode.c_str() + Bitcode.size(), + "Bitcode for test"); + std::string errMsg; + MP = getBitcodeModuleProvider(BitcodeBuffer, Context, &errMsg); + if (MP == NULL) { + ADD_FAILURE() << errMsg; + delete BitcodeBuffer; + return NULL; + } + ExecutionEngine *TheJIT = EngineBuilder(MP) + .setEngineKind(EngineKind::JIT) + .setErrorStr(&errMsg) + .create(); + if (TheJIT == NULL) { + ADD_FAILURE() << errMsg; + delete MP; + MP = NULL; + return NULL; + } + return TheJIT; +} + +TEST(LazyLoadedJITTest, EagerCompiledRecursionThroughGhost) { + LLVMContext Context; + const std::string Bitcode = + AssembleToBitcode(Context, + "define i32 @recur1(i32 %a) { " + " %zero = icmp eq i32 %a, 0 " + " br i1 %zero, label %done, label %notdone " + "done: " + " ret i32 3 " + "notdone: " + " %am1 = sub i32 %a, 1 " + " %result = call i32 @recur2(i32 %am1) " + " ret i32 %result " + "} " + " " + "define i32 @recur2(i32 %b) { " + " %result = call i32 @recur1(i32 %b) " + " ret i32 %result " + "} "); + ASSERT_FALSE(Bitcode.empty()) << "Assembling failed"; + ModuleProvider *MP; + OwningPtr<ExecutionEngine> TheJIT(getJITFromBitcode(Context, Bitcode, MP)); + ASSERT_TRUE(TheJIT.get()) << "Failed to create JIT."; + TheJIT->DisableLazyCompilation(true); + + Module *M = MP->getModule(); + Function *recur1IR = M->getFunction("recur1"); + Function *recur2IR = M->getFunction("recur2"); + EXPECT_TRUE(recur1IR->hasNotBeenReadFromBitcode()); + EXPECT_TRUE(recur2IR->hasNotBeenReadFromBitcode()); + + int32_t (*recur1)(int32_t) = reinterpret_cast<int32_t(*)(int32_t)>( + (intptr_t)TheJIT->getPointerToFunction(recur1IR)); + EXPECT_EQ(3, recur1(4)); +} + // This code is copied from JITEventListenerTest, but it only runs once for all // the tests in this directory. Everything seems fine, but that's strange // behavior. diff --git a/unittests/ExecutionEngine/JIT/Makefile b/unittests/ExecutionEngine/JIT/Makefile index 8de390b..f5abe75 100644 --- a/unittests/ExecutionEngine/JIT/Makefile +++ b/unittests/ExecutionEngine/JIT/Makefile @@ -9,7 +9,7 @@ LEVEL = ../../.. TESTNAME = JIT -LINK_COMPONENTS := asmparser core support jit native +LINK_COMPONENTS := asmparser bitreader bitwriter core jit native support include $(LEVEL)/Makefile.config include $(LLVM_SRC_ROOT)/unittests/Makefile.unittest diff --git a/unittests/Support/LeakDetectorTest.cpp b/unittests/Support/LeakDetectorTest.cpp new file mode 100644 index 0000000..85ef046 --- /dev/null +++ b/unittests/Support/LeakDetectorTest.cpp @@ -0,0 +1,29 @@ +//===- llvm/unittest/LeakDetector/LeakDetector.cpp - LeakDetector tests ---===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +#include "gtest/gtest.h" +#include "llvm/Support/LeakDetector.h" + +using namespace llvm; + +namespace { + +#ifdef GTEST_HAS_DEATH_TEST +TEST(LeakDetector, Death1) { + LeakDetector::addGarbageObject((void*) 1); + LeakDetector::addGarbageObject((void*) 2); + + EXPECT_DEATH(LeakDetector::addGarbageObject((void*) 1), + ".*Ts.count\\(o\\) == 0 && \"Object already in set!\""); + EXPECT_DEATH(LeakDetector::addGarbageObject((void*) 2), + "Cache != o && \"Object already in set!\""); +} +#endif + +} diff --git a/unittests/VMCore/DerivedTypesTest.cpp b/unittests/VMCore/DerivedTypesTest.cpp new file mode 100644 index 0000000..11b4dff --- /dev/null +++ b/unittests/VMCore/DerivedTypesTest.cpp @@ -0,0 +1,31 @@ +//===- llvm/unittest/VMCore/DerivedTypesTest.cpp - Types unit tests -------===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +#include "gtest/gtest.h" +#include "../lib/VMCore/LLVMContextImpl.h" +#include "llvm/Type.h" +#include "llvm/DerivedTypes.h" +#include "llvm/LLVMContext.h" +using namespace llvm; + +namespace { + +TEST(OpaqueTypeTest, RegisterWithContext) { + LLVMContext C; + LLVMContextImpl *pImpl = C.pImpl; + + EXPECT_EQ(0u, pImpl->OpaqueTypes.size()); + { + PATypeHolder Type = OpaqueType::get(C); + EXPECT_EQ(1u, pImpl->OpaqueTypes.size()); + } + EXPECT_EQ(0u, pImpl->OpaqueTypes.size()); +} + +} // namespace diff --git a/unittests/VMCore/MetadataTest.cpp b/unittests/VMCore/MetadataTest.cpp index 4bd777b..e118568 100644 --- a/unittests/VMCore/MetadataTest.cpp +++ b/unittests/VMCore/MetadataTest.cpp @@ -92,24 +92,13 @@ TEST(MDNodeTest, Simple) { (void) n3; #endif - EXPECT_EQ(3u, n1->getNumElements()); - EXPECT_EQ(s1, n1->getElement(0)); - EXPECT_EQ(CI, n1->getElement(1)); - EXPECT_EQ(s2, n1->getElement(2)); + EXPECT_EQ(3u, n1->getNumOperands()); + EXPECT_EQ(s1, n1->getOperand(0)); + EXPECT_EQ(CI, n1->getOperand(1)); + EXPECT_EQ(s2, n1->getOperand(2)); - EXPECT_EQ(1u, n2->getNumElements()); - EXPECT_EQ(n1, n2->getElement(0)); - - std::string Str; - raw_string_ostream oss(Str); - n1->print(oss); - EXPECT_STREQ("!0 = metadata !{metadata !\"abc\", i8 0, metadata !\"123\"}\n", - oss.str().c_str()); - Str.clear(); - n2->print(oss); - EXPECT_STREQ("!0 = metadata !{metadata !1}\n" - "!1 = metadata !{metadata !\"abc\", i8 0, metadata !\"123\"}\n", - oss.str().c_str()); + EXPECT_EQ(1u, n2->getNumOperands()); + EXPECT_EQ(n1, n2->getOperand(0)); } TEST(MDNodeTest, Delete) { @@ -123,11 +112,6 @@ TEST(MDNodeTest, Delete) { EXPECT_EQ(n, wvh); delete I; - - std::string Str; - raw_string_ostream oss(Str); - wvh->print(oss); - EXPECT_STREQ("!0 = metadata !{null}\n", oss.str().c_str()); } TEST(NamedMDNodeTest, Search) { @@ -147,8 +131,7 @@ TEST(NamedMDNodeTest, Search) { std::string Str; raw_string_ostream oss(Str); NMD->print(oss); - EXPECT_STREQ("!llvm.NMD1 = !{!0, !1}\n!0 = metadata !{i32 1}\n" - "!1 = metadata !{i32 2}\n", + EXPECT_STREQ("!llvm.NMD1 = !{!0, !1}\n", oss.str().c_str()); } } |