summaryrefslogtreecommitdiffstats
path: root/unittests
diff options
context:
space:
mode:
Diffstat (limited to 'unittests')
-rw-r--r--unittests/ADT/APFloatTest.cpp22
-rw-r--r--unittests/ADT/DeltaAlgorithmTest.cpp4
-rw-r--r--unittests/ADT/StringRefTest.cpp18
-rw-r--r--unittests/ExecutionEngine/JIT/JITTest.cpp166
-rw-r--r--unittests/ExecutionEngine/JIT/Makefile2
-rw-r--r--unittests/Support/LeakDetectorTest.cpp29
-rw-r--r--unittests/VMCore/DerivedTypesTest.cpp31
-rw-r--r--unittests/VMCore/MetadataTest.cpp31
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());
}
}
OpenPOWER on IntegriCloud