aboutsummaryrefslogtreecommitdiffstats
path: root/unittests
diff options
context:
space:
mode:
Diffstat (limited to 'unittests')
-rw-r--r--unittests/ADT/APFloatTest.cpp9
-rw-r--r--unittests/ADT/CMakeLists.txt2
-rw-r--r--unittests/ADT/IntrusiveRefCntPtrTest.cpp8
-rw-r--r--unittests/ADT/PointerUnionTest.cpp64
-rw-r--r--unittests/ADT/StringRefTest.cpp52
-rw-r--r--unittests/ADT/polymorphic_ptr_test.cpp129
-rw-r--r--unittests/Analysis/CFGTest.cpp17
-rw-r--r--unittests/CMakeLists.txt10
-rw-r--r--unittests/CodeGen/CMakeLists.txt13
-rw-r--r--unittests/CodeGen/DIEHashTest.cpp517
-rw-r--r--unittests/CodeGen/Makefile16
-rw-r--r--unittests/DebugInfo/DWARFFormValueTest.cpp22
-rw-r--r--unittests/ExecutionEngine/JIT/JITMemoryManagerTest.cpp10
-rw-r--r--unittests/ExecutionEngine/JIT/JITTest.cpp28
-rw-r--r--unittests/ExecutionEngine/MCJIT/CMakeLists.txt2
-rw-r--r--unittests/ExecutionEngine/MCJIT/MCJITCAPITest.cpp10
-rw-r--r--unittests/ExecutionEngine/MCJIT/MCJITMemoryManagerTest.cpp24
-rw-r--r--unittests/ExecutionEngine/MCJIT/MCJITMultipleModuleTest.cpp395
-rw-r--r--unittests/ExecutionEngine/MCJIT/MCJITTest.cpp108
-rw-r--r--unittests/ExecutionEngine/MCJIT/MCJITTestBase.h142
-rw-r--r--unittests/ExecutionEngine/MCJIT/Makefile2
-rw-r--r--unittests/IR/CMakeLists.txt1
-rw-r--r--unittests/IR/IRBuilderTest.cpp55
-rw-r--r--unittests/IR/InstructionsTest.cpp53
-rw-r--r--unittests/IR/LegacyPassManagerTest.cpp559
-rw-r--r--unittests/IR/PassManagerTest.cpp625
-rw-r--r--unittests/IR/ValueTest.cpp40
-rw-r--r--unittests/IR/VerifierTest.cpp7
-rw-r--r--unittests/IR/WaymarkTest.cpp1
-rw-r--r--unittests/MC/CMakeLists.txt11
-rw-r--r--unittests/MC/MCAtomTest.cpp31
-rw-r--r--unittests/MC/Makefile15
-rw-r--r--unittests/Makefile4
-rw-r--r--unittests/Option/OptionParsingTest.cpp50
-rw-r--r--unittests/Option/Opts.td2
-rw-r--r--unittests/Support/BlockFrequencyTest.cpp133
-rw-r--r--unittests/Support/CMakeLists.txt5
-rw-r--r--unittests/Support/CompressionTest.cpp6
-rw-r--r--unittests/Support/ConstantRangeTest.cpp3
-rw-r--r--unittests/Support/ErrorOrTest.cpp38
-rw-r--r--unittests/Support/IntegersSubsetTest.cpp326
-rw-r--r--unittests/Support/LocaleTest.cpp100
-rw-r--r--unittests/Support/MemoryBufferTest.cpp26
-rw-r--r--unittests/Support/Path.cpp125
-rw-r--r--unittests/Support/ProcessTest.cpp28
-rw-r--r--unittests/Support/ProgramTest.cpp105
-rw-r--r--unittests/Support/RegexTest.cpp8
-rw-r--r--unittests/Support/SourceMgrTest.cpp174
-rw-r--r--unittests/Support/ThreadLocalTest.cpp38
-rw-r--r--unittests/Support/UnicodeTest.cpp93
-rw-r--r--unittests/Support/YAMLIOTest.cpp441
-rw-r--r--unittests/Transforms/Utils/SpecialCaseList.cpp82
52 files changed, 3516 insertions, 1249 deletions
diff --git a/unittests/ADT/APFloatTest.cpp b/unittests/ADT/APFloatTest.cpp
index 3b69de2..e57c8d4 100644
--- a/unittests/ADT/APFloatTest.cpp
+++ b/unittests/ADT/APFloatTest.cpp
@@ -866,10 +866,11 @@ TEST(APFloatTest, toString) {
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));
- ASSERT_EQ("873.1834", convertToString(873.1834, 0, 1));
- ASSERT_EQ("8.731834E+2", convertToString(873.1834, 0, 0));
+ ASSERT_EQ("0.78539816339744828", convertToString(0.78539816339744830961, 0, 3));
+ ASSERT_EQ("4.9406564584124654E-324", convertToString(4.9406564584124654e-324, 0, 3));
+ ASSERT_EQ("873.18340000000001", convertToString(873.1834, 0, 1));
+ ASSERT_EQ("8.7318340000000001E+2", convertToString(873.1834, 0, 0));
+ ASSERT_EQ("1.7976931348623157E+308", convertToString(1.7976931348623157E+308, 0, 0));
}
TEST(APFloatTest, toInteger) {
diff --git a/unittests/ADT/CMakeLists.txt b/unittests/ADT/CMakeLists.txt
index 9aad793..8ad303a 100644
--- a/unittests/ADT/CMakeLists.txt
+++ b/unittests/ADT/CMakeLists.txt
@@ -21,6 +21,7 @@ set(ADTSources
MapVectorTest.cpp
OptionalTest.cpp
PackedVectorTest.cpp
+ PointerUnionTest.cpp
SCCIteratorTest.cpp
SmallPtrSetTest.cpp
SmallStringTest.cpp
@@ -34,6 +35,7 @@ set(ADTSources
TripleTest.cpp
TwineTest.cpp
VariadicFunctionTest.cpp
+ polymorphic_ptr_test.cpp
)
# They cannot be compiled on MSVC9 due to its bug.
diff --git a/unittests/ADT/IntrusiveRefCntPtrTest.cpp b/unittests/ADT/IntrusiveRefCntPtrTest.cpp
index 0c8c4ca..c67ec13 100644
--- a/unittests/ADT/IntrusiveRefCntPtrTest.cpp
+++ b/unittests/ADT/IntrusiveRefCntPtrTest.cpp
@@ -10,11 +10,13 @@
#include "llvm/ADT/IntrusiveRefCntPtr.h"
#include "gtest/gtest.h"
-namespace llvm {
-
-struct VirtualRefCounted : public RefCountedBaseVPTR {
+namespace {
+struct VirtualRefCounted : public llvm::RefCountedBaseVPTR {
virtual void f() {}
};
+}
+
+namespace llvm {
// Run this test with valgrind to detect memory leaks.
TEST(IntrusiveRefCntPtr, RefCountedBaseVPTRCopyDoesNotLeak) {
diff --git a/unittests/ADT/PointerUnionTest.cpp b/unittests/ADT/PointerUnionTest.cpp
new file mode 100644
index 0000000..7eb7181
--- /dev/null
+++ b/unittests/ADT/PointerUnionTest.cpp
@@ -0,0 +1,64 @@
+//===- llvm/unittest/ADT/PointerUnionTest.cpp - Optional 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 "llvm/ADT/PointerUnion.h"
+using namespace llvm;
+
+namespace {
+
+typedef PointerUnion<int*, float*> PU;
+
+// Test fixture
+class PointerUnionTest : public testing::Test {
+};
+
+float f = 3.14f;
+int i = 42;
+
+const PU a(&f);
+const PU b(&i);
+const PU n;
+
+TEST_F(PointerUnionTest, Comparison) {
+ EXPECT_TRUE(a != b);
+ EXPECT_FALSE(a == b);
+ EXPECT_TRUE(b != n);
+ EXPECT_FALSE(b == n);
+}
+
+TEST_F(PointerUnionTest, Null) {
+ EXPECT_FALSE(a.isNull());
+ EXPECT_FALSE(b.isNull());
+ EXPECT_TRUE(n.isNull());
+ EXPECT_FALSE(!a);
+ EXPECT_FALSE(!b);
+ EXPECT_TRUE(!n);
+ // workaround an issue with EXPECT macros and explicit bool
+ EXPECT_TRUE((bool)a);
+ EXPECT_TRUE((bool)b);
+ EXPECT_FALSE(n);
+}
+
+TEST_F(PointerUnionTest, Is) {
+ EXPECT_FALSE(a.is<int*>());
+ EXPECT_TRUE(a.is<float*>());
+ EXPECT_TRUE(b.is<int*>());
+ EXPECT_FALSE(b.is<float*>());
+ EXPECT_TRUE(n.is<int*>());
+ EXPECT_FALSE(n.is<float*>());
+}
+
+TEST_F(PointerUnionTest, Get) {
+ EXPECT_EQ(a.get<float*>(), &f);
+ EXPECT_EQ(b.get<int*>(), &i);
+ EXPECT_EQ(n.get<int*>(), (int*)0);
+}
+
+} // end anonymous namespace
diff --git a/unittests/ADT/StringRefTest.cpp b/unittests/ADT/StringRefTest.cpp
index fa87cd0..88691ae 100644
--- a/unittests/ADT/StringRefTest.cpp
+++ b/unittests/ADT/StringRefTest.cpp
@@ -8,6 +8,7 @@
//===----------------------------------------------------------------------===//
#include "llvm/ADT/StringRef.h"
+#include "llvm/ADT/StringExtras.h"
#include "llvm/ADT/Hashing.h"
#include "llvm/ADT/SmallVector.h"
#include "llvm/Support/raw_ostream.h"
@@ -60,6 +61,9 @@ TEST(StringRefTest, StringOps) {
EXPECT_EQ( 0, StringRef("AaB").compare_lower("aab"));
EXPECT_EQ( 1, StringRef("AaB").compare_lower("AAA"));
EXPECT_EQ(-1, StringRef("AaB").compare_lower("aaBb"));
+ EXPECT_EQ(-1, StringRef("AaB").compare_lower("bb"));
+ EXPECT_EQ( 1, StringRef("aaBb").compare_lower("AaB"));
+ EXPECT_EQ( 1, StringRef("bb").compare_lower("AaB"));
EXPECT_EQ( 1, StringRef("AaB").compare_lower("aA"));
EXPECT_EQ( 1, StringRef("\xFF").compare_lower("\1"));
@@ -247,19 +251,41 @@ TEST(StringRefTest, Trim) {
TEST(StringRefTest, StartsWith) {
StringRef Str("hello");
+ EXPECT_TRUE(Str.startswith(""));
EXPECT_TRUE(Str.startswith("he"));
EXPECT_FALSE(Str.startswith("helloworld"));
EXPECT_FALSE(Str.startswith("hi"));
}
+TEST(StringRefTest, StartsWithLower) {
+ StringRef Str("heLLo");
+ EXPECT_TRUE(Str.startswith_lower(""));
+ EXPECT_TRUE(Str.startswith_lower("he"));
+ EXPECT_TRUE(Str.startswith_lower("hell"));
+ EXPECT_TRUE(Str.startswith_lower("HELlo"));
+ EXPECT_FALSE(Str.startswith_lower("helloworld"));
+ EXPECT_FALSE(Str.startswith_lower("hi"));
+}
+
TEST(StringRefTest, EndsWith) {
StringRef Str("hello");
+ EXPECT_TRUE(Str.endswith(""));
EXPECT_TRUE(Str.endswith("lo"));
EXPECT_FALSE(Str.endswith("helloworld"));
EXPECT_FALSE(Str.endswith("worldhello"));
EXPECT_FALSE(Str.endswith("so"));
}
+TEST(StringRefTest, EndsWithLower) {
+ StringRef Str("heLLo");
+ EXPECT_TRUE(Str.endswith_lower(""));
+ EXPECT_TRUE(Str.endswith_lower("lo"));
+ EXPECT_TRUE(Str.endswith_lower("LO"));
+ EXPECT_TRUE(Str.endswith_lower("ELlo"));
+ EXPECT_FALSE(Str.endswith_lower("helloworld"));
+ EXPECT_FALSE(Str.endswith_lower("hi"));
+}
+
TEST(StringRefTest, Find) {
StringRef Str("hello");
EXPECT_EQ(2U, Str.find('l'));
@@ -477,6 +503,32 @@ TEST(StringRefTest, getAsUnsignedIntegerBadStrings) {
}
}
+static const char *join_input[] = { "a", "b", "c" };
+static const char join_result1[] = "a";
+static const char join_result2[] = "a:b:c";
+static const char join_result3[] = "a::b::c";
+
+TEST(StringRefTest, joinStrings) {
+ std::vector<StringRef> v1;
+ std::vector<std::string> v2;
+ for (size_t i = 0; i < array_lengthof(join_input); ++i) {
+ v1.push_back(join_input[i]);
+ v2.push_back(join_input[i]);
+ }
+ bool v1_join1 = join(v1.begin(), v1.begin() + 1, ":") == join_result1;
+ EXPECT_TRUE(v1_join1);
+ bool v1_join2 = join(v1.begin(), v1.end(), ":") == join_result2;
+ EXPECT_TRUE(v1_join2);
+ bool v1_join3 = join(v1.begin(), v1.end(), "::") == join_result3;
+ EXPECT_TRUE(v1_join3);
+
+ bool v2_join1 = join(v2.begin(), v2.begin() + 1, ":") == join_result1;
+ EXPECT_TRUE(v2_join1);
+ bool v2_join2 = join(v2.begin(), v2.end(), ":") == join_result2;
+ EXPECT_TRUE(v2_join2);
+ bool v2_join3 = join(v2.begin(), v2.end(), "::") == join_result3;
+ EXPECT_TRUE(v2_join3);
+}
} // end anonymous namespace
diff --git a/unittests/ADT/polymorphic_ptr_test.cpp b/unittests/ADT/polymorphic_ptr_test.cpp
new file mode 100644
index 0000000..bd5d838
--- /dev/null
+++ b/unittests/ADT/polymorphic_ptr_test.cpp
@@ -0,0 +1,129 @@
+//===- llvm/unittest/ADT/polymorphic_ptr.h - polymorphic_ptr<T> 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/ADT/polymorphic_ptr.h"
+#include "llvm/Support/raw_ostream.h"
+
+using namespace llvm;
+
+namespace {
+
+struct S {
+ S(int x) : x(x) {}
+ S *clone() { return new S(*this); }
+ int x;
+};
+
+// A function that forces the return of a copy.
+template <typename T>
+T dummy_copy(const T &arg) { return arg; }
+
+TEST(polymorphic_ptr_test, Basic) {
+ polymorphic_ptr<S> null;
+ EXPECT_FALSE((bool)null);
+ EXPECT_TRUE(!null);
+ EXPECT_EQ((S*)0, null.get());
+
+ S *s = new S(42);
+ polymorphic_ptr<S> p(s);
+ EXPECT_TRUE((bool)p);
+ EXPECT_FALSE(!p);
+ EXPECT_TRUE(p != null);
+ EXPECT_FALSE(p == null);
+ EXPECT_TRUE(p == s);
+ EXPECT_TRUE(s == p);
+ EXPECT_FALSE(p != s);
+ EXPECT_FALSE(s != p);
+ EXPECT_EQ(s, &*p);
+ EXPECT_EQ(s, p.operator->());
+ EXPECT_EQ(s, p.get());
+ EXPECT_EQ(42, p->x);
+
+ EXPECT_EQ(s, p.take());
+ EXPECT_FALSE((bool)p);
+ EXPECT_TRUE(!p);
+ p = s;
+ EXPECT_TRUE((bool)p);
+ EXPECT_FALSE(!p);
+ EXPECT_EQ(s, &*p);
+ EXPECT_EQ(s, p.operator->());
+ EXPECT_EQ(s, p.get());
+ EXPECT_EQ(42, p->x);
+
+ polymorphic_ptr<S> p2((llvm_move(p)));
+#if !LLVM_HAS_RVALUE_REFERENCES
+ // 'p' may not have been moved from in C++98, fake it for the test.
+ p2 = p.take();
+#endif
+ EXPECT_FALSE((bool)p);
+ EXPECT_TRUE(!p);
+ EXPECT_TRUE((bool)p2);
+ EXPECT_FALSE(!p2);
+ EXPECT_EQ(s, &*p2);
+
+ using std::swap;
+ swap(p, p2);
+ EXPECT_TRUE((bool)p);
+ EXPECT_FALSE(!p);
+ EXPECT_EQ(s, &*p);
+ EXPECT_FALSE((bool)p2);
+ EXPECT_TRUE(!p2);
+
+ // Force copies and that everything survives.
+ polymorphic_ptr<S> p3 = dummy_copy(polymorphic_ptr<S>(p));
+ EXPECT_TRUE((bool)p3);
+ EXPECT_FALSE(!p3);
+ EXPECT_NE(s, &*p3);
+ EXPECT_EQ(42, p3->x);
+
+ // Force copies of null without trying to dereference anything.
+ polymorphic_ptr<S> null_copy = dummy_copy(polymorphic_ptr<S>(null));
+ EXPECT_FALSE((bool)null_copy);
+ EXPECT_TRUE(!null_copy);
+ EXPECT_EQ(null, null_copy);
+}
+
+struct Base {
+ virtual ~Base() {}
+ virtual Base *clone() = 0;
+ virtual StringRef name() { return "Base"; }
+};
+
+struct DerivedA : Base {
+ virtual DerivedA *clone() { return new DerivedA(); }
+ virtual StringRef name() { return "DerivedA"; }
+};
+struct DerivedB : Base {
+ virtual DerivedB *clone() { return new DerivedB(); }
+ virtual StringRef name() { return "DerivedB"; }
+};
+
+TEST(polymorphic_ptr_test, Polymorphism) {
+ polymorphic_ptr<Base> a(new DerivedA());
+ polymorphic_ptr<Base> b(new DerivedB());
+
+ EXPECT_EQ("DerivedA", a->name());
+ EXPECT_EQ("DerivedB", b->name());
+
+ polymorphic_ptr<Base> copy = dummy_copy(a);
+ EXPECT_NE(a, copy);
+ EXPECT_EQ("DerivedA", copy->name());
+
+ copy = dummy_copy(b);
+ EXPECT_NE(b, copy);
+ EXPECT_EQ("DerivedB", copy->name());
+
+ // Test creating a copy out of a temporary directly.
+ copy = dummy_copy<polymorphic_ptr<Base> >(new DerivedA());
+ EXPECT_NE(a, copy);
+ EXPECT_EQ("DerivedA", copy->name());
+}
+
+}
diff --git a/unittests/Analysis/CFGTest.cpp b/unittests/Analysis/CFGTest.cpp
index 2358803..e931709 100644
--- a/unittests/Analysis/CFGTest.cpp
+++ b/unittests/Analysis/CFGTest.cpp
@@ -147,6 +147,23 @@ TEST_F(IsPotentiallyReachableTest, SameBlockPath) {
ExpectPath(true);
}
+TEST_F(IsPotentiallyReachableTest, SameBlockNoLoop) {
+ ParseAssembly(
+ "define void @test() {\n"
+ "entry:\n"
+ " br label %middle\n"
+ "middle:\n"
+ " %B = bitcast i8 undef to i8\n"
+ " bitcast i8 undef to i8\n"
+ " bitcast i8 undef to i8\n"
+ " %A = bitcast i8 undef to i8\n"
+ " br label %nextblock\n"
+ "nextblock:\n"
+ " ret void\n"
+ "}\n");
+ ExpectPath(false);
+}
+
TEST_F(IsPotentiallyReachableTest, StraightNoPath) {
ParseAssembly(
"define void @test() {\n"
diff --git a/unittests/CMakeLists.txt b/unittests/CMakeLists.txt
index 53b7e9c..52702ba 100644
--- a/unittests/CMakeLists.txt
+++ b/unittests/CMakeLists.txt
@@ -7,11 +7,13 @@ endfunction()
add_subdirectory(ADT)
add_subdirectory(Analysis)
-add_subdirectory(ExecutionEngine)
add_subdirectory(Bitcode)
+add_subdirectory(CodeGen)
+add_subdirectory(DebugInfo)
+add_subdirectory(ExecutionEngine)
+add_subdirectory(IR)
+add_subdirectory(MC)
+add_subdirectory(Object)
add_subdirectory(Option)
add_subdirectory(Support)
add_subdirectory(Transforms)
-add_subdirectory(IR)
-add_subdirectory(DebugInfo)
-add_subdirectory(Object)
diff --git a/unittests/CodeGen/CMakeLists.txt b/unittests/CodeGen/CMakeLists.txt
new file mode 100644
index 0000000..5973bae
--- /dev/null
+++ b/unittests/CodeGen/CMakeLists.txt
@@ -0,0 +1,13 @@
+set(LLVM_LINK_COMPONENTS
+ asmprinter
+ codegen
+ support
+ )
+
+set(CodeGenSources
+ DIEHashTest.cpp
+ )
+
+add_llvm_unittest(CodeGenTests
+ ${CodeGenSources}
+ )
diff --git a/unittests/CodeGen/DIEHashTest.cpp b/unittests/CodeGen/DIEHashTest.cpp
new file mode 100644
index 0000000..8d8fc39
--- /dev/null
+++ b/unittests/CodeGen/DIEHashTest.cpp
@@ -0,0 +1,517 @@
+//===- llvm/unittest/DebugInfo/DWARFFormValueTest.cpp ---------------------===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#include "../lib/CodeGen/AsmPrinter/DIE.h"
+#include "../lib/CodeGen/AsmPrinter/DIEHash.h"
+#include "llvm/Support/Dwarf.h"
+#include "llvm/Support/Debug.h"
+#include "llvm/Support/Format.h"
+#include "gtest/gtest.h"
+
+using namespace llvm;
+
+namespace {
+TEST(DIEHashTest, Data1) {
+ DIEHash Hash;
+ DIE Die(dwarf::DW_TAG_base_type);
+ DIEInteger Size(4);
+ Die.addValue(dwarf::DW_AT_byte_size, dwarf::DW_FORM_data1, &Size);
+ uint64_t MD5Res = Hash.computeTypeSignature(Die);
+ ASSERT_EQ(0x1AFE116E83701108ULL, MD5Res);
+}
+
+// struct {};
+TEST(DIEHashTest, TrivialType) {
+ DIE Unnamed(dwarf::DW_TAG_structure_type);
+ DIEInteger One(1);
+ Unnamed.addValue(dwarf::DW_AT_byte_size, dwarf::DW_FORM_data1, &One);
+
+ // Line and file number are ignored.
+ Unnamed.addValue(dwarf::DW_AT_decl_file, dwarf::DW_FORM_data1, &One);
+ Unnamed.addValue(dwarf::DW_AT_decl_line, dwarf::DW_FORM_data1, &One);
+ uint64_t MD5Res = DIEHash().computeTypeSignature(Unnamed);
+
+ // The exact same hash GCC produces for this DIE.
+ ASSERT_EQ(0x715305ce6cfd9ad1ULL, MD5Res);
+}
+
+// struct foo { };
+TEST(DIEHashTest, NamedType) {
+ DIE Foo(dwarf::DW_TAG_structure_type);
+ DIEInteger One(1);
+ DIEString FooStr(&One, "foo");
+ Foo.addValue(dwarf::DW_AT_name, dwarf::DW_FORM_strp, &FooStr);
+ Foo.addValue(dwarf::DW_AT_byte_size, dwarf::DW_FORM_data1, &One);
+
+ uint64_t MD5Res = DIEHash().computeTypeSignature(Foo);
+
+ // The exact same hash GCC produces for this DIE.
+ ASSERT_EQ(0xd566dbd2ca5265ffULL, MD5Res);
+}
+
+// namespace space { struct foo { }; }
+TEST(DIEHashTest, NamespacedType) {
+ DIE CU(dwarf::DW_TAG_compile_unit);
+
+ DIE *Space = new DIE(dwarf::DW_TAG_namespace);
+ DIEInteger One(1);
+ DIEString SpaceStr(&One, "space");
+ Space->addValue(dwarf::DW_AT_name, dwarf::DW_FORM_strp, &SpaceStr);
+ // DW_AT_declaration is ignored.
+ Space->addValue(dwarf::DW_AT_declaration, dwarf::DW_FORM_flag_present, &One);
+ // sibling?
+
+ DIE *Foo = new DIE(dwarf::DW_TAG_structure_type);
+ DIEString FooStr(&One, "foo");
+ Foo->addValue(dwarf::DW_AT_name, dwarf::DW_FORM_strp, &FooStr);
+ Foo->addValue(dwarf::DW_AT_byte_size, dwarf::DW_FORM_data1, &One);
+
+ Space->addChild(Foo);
+ CU.addChild(Space);
+
+ uint64_t MD5Res = DIEHash().computeTypeSignature(*Foo);
+
+ // The exact same hash GCC produces for this DIE.
+ ASSERT_EQ(0x7b80381fd17f1e33ULL, MD5Res);
+}
+
+// struct { int member; };
+TEST(DIEHashTest, TypeWithMember) {
+ DIE Unnamed(dwarf::DW_TAG_structure_type);
+ DIEInteger Four(4);
+ Unnamed.addValue(dwarf::DW_AT_byte_size, dwarf::DW_FORM_data1, &Four);
+
+ DIE *Member = new DIE(dwarf::DW_TAG_member);
+ DIEString MemberStr(&Four, "member");
+ Member->addValue(dwarf::DW_AT_name, dwarf::DW_FORM_strp, &MemberStr);
+ DIEInteger Zero(0);
+ Member->addValue(dwarf::DW_AT_data_member_location, dwarf::DW_FORM_data1, &Zero);
+
+ Unnamed.addChild(Member);
+
+ DIE Int(dwarf::DW_TAG_base_type);
+ DIEString IntStr(&Four, "int");
+ Int.addValue(dwarf::DW_AT_name, dwarf::DW_FORM_strp, &IntStr);
+ Int.addValue(dwarf::DW_AT_byte_size, dwarf::DW_FORM_data1, &Four);
+ DIEInteger Five(5);
+ Int.addValue(dwarf::DW_AT_encoding, dwarf::DW_FORM_data1, &Five);
+
+ DIEEntry IntRef(&Int);
+ Member->addValue(dwarf::DW_AT_type, dwarf::DW_FORM_ref4, &IntRef);
+
+ uint64_t MD5Res = DIEHash().computeTypeSignature(Unnamed);
+
+ ASSERT_EQ(0x5646aa436b7e07c6ULL, MD5Res);
+}
+
+// struct foo { int mem1, mem2; };
+TEST(DIEHashTest, ReusedType) {
+ DIE Unnamed(dwarf::DW_TAG_structure_type);
+ DIEInteger Eight(8);
+ Unnamed.addValue(dwarf::DW_AT_byte_size, dwarf::DW_FORM_data1, &Eight);
+
+ DIE *Mem1 = new DIE(dwarf::DW_TAG_member);
+ DIEInteger Four(4);
+ DIEString Mem1Str(&Four, "mem1");
+ Mem1->addValue(dwarf::DW_AT_name, dwarf::DW_FORM_strp, &Mem1Str);
+ DIEInteger Zero(0);
+ Mem1->addValue(dwarf::DW_AT_data_member_location, dwarf::DW_FORM_data1, &Zero);
+
+ Unnamed.addChild(Mem1);
+
+ DIE *Mem2 = new DIE(dwarf::DW_TAG_member);
+ DIEString Mem2Str(&Four, "mem2");
+ Mem2->addValue(dwarf::DW_AT_name, dwarf::DW_FORM_strp, &Mem2Str);
+ Mem2->addValue(dwarf::DW_AT_data_member_location, dwarf::DW_FORM_data1, &Four);
+
+ Unnamed.addChild(Mem2);
+
+ DIE Int(dwarf::DW_TAG_base_type);
+ DIEString IntStr(&Four, "int");
+ Int.addValue(dwarf::DW_AT_name, dwarf::DW_FORM_strp, &IntStr);
+ Int.addValue(dwarf::DW_AT_byte_size, dwarf::DW_FORM_data1, &Four);
+ DIEInteger Five(5);
+ Int.addValue(dwarf::DW_AT_encoding, dwarf::DW_FORM_data1, &Five);
+
+ DIEEntry IntRef(&Int);
+ Mem1->addValue(dwarf::DW_AT_type, dwarf::DW_FORM_ref4, &IntRef);
+ Mem2->addValue(dwarf::DW_AT_type, dwarf::DW_FORM_ref4, &IntRef);
+
+ uint64_t MD5Res = DIEHash().computeTypeSignature(Unnamed);
+
+ ASSERT_EQ(0x3a7dc3ed7b76b2f8ULL, MD5Res);
+}
+
+// struct foo { static foo f; };
+TEST(DIEHashTest, RecursiveType) {
+ DIE Foo(dwarf::DW_TAG_structure_type);
+ DIEInteger One(1);
+ Foo.addValue(dwarf::DW_AT_byte_size, dwarf::DW_FORM_data1, &One);
+ DIEString FooStr(&One, "foo");
+ Foo.addValue(dwarf::DW_AT_name, dwarf::DW_FORM_strp, &FooStr);
+
+ DIE *Mem = new DIE(dwarf::DW_TAG_member);
+ DIEString MemStr(&One, "mem");
+ Mem->addValue(dwarf::DW_AT_name, dwarf::DW_FORM_strp, &MemStr);
+ DIEEntry FooRef(&Foo);
+ Mem->addValue(dwarf::DW_AT_type, dwarf::DW_FORM_ref4, &FooRef);
+ // DW_AT_external and DW_AT_declaration are ignored anyway, so skip them.
+
+ Foo.addChild(Mem);
+
+ uint64_t MD5Res = DIEHash().computeTypeSignature(Foo);
+
+ ASSERT_EQ(0x73d8b25aef227b06ULL, MD5Res);
+}
+
+// struct foo { foo *mem; };
+TEST(DIEHashTest, Pointer) {
+ DIE Foo(dwarf::DW_TAG_structure_type);
+ DIEInteger Eight(8);
+ Foo.addValue(dwarf::DW_AT_byte_size, dwarf::DW_FORM_data1, &Eight);
+ DIEString FooStr(&Eight, "foo");
+ Foo.addValue(dwarf::DW_AT_name, dwarf::DW_FORM_strp, &FooStr);
+
+ DIE *Mem = new DIE(dwarf::DW_TAG_member);
+ DIEString MemStr(&Eight, "mem");
+ Mem->addValue(dwarf::DW_AT_name, dwarf::DW_FORM_strp, &MemStr);
+ DIEInteger Zero(0);
+ Mem->addValue(dwarf::DW_AT_data_member_location, dwarf::DW_FORM_data1, &Zero);
+
+ DIE FooPtr(dwarf::DW_TAG_pointer_type);
+ FooPtr.addValue(dwarf::DW_AT_byte_size, dwarf::DW_FORM_data1, &Eight);
+ DIEEntry FooRef(&Foo);
+ FooPtr.addValue(dwarf::DW_AT_type, dwarf::DW_FORM_ref4, &FooRef);
+
+ DIEEntry FooPtrRef(&FooPtr);
+ Mem->addValue(dwarf::DW_AT_type, dwarf::DW_FORM_ref4, &FooPtrRef);
+
+ Foo.addChild(Mem);
+
+ uint64_t MD5Res = DIEHash().computeTypeSignature(Foo);
+
+ ASSERT_EQ(0x74ea73862e8708d2ULL, MD5Res);
+}
+
+// struct foo { foo &mem; };
+TEST(DIEHashTest, Reference) {
+ DIE Foo(dwarf::DW_TAG_structure_type);
+ DIEInteger Eight(8);
+ Foo.addValue(dwarf::DW_AT_byte_size, dwarf::DW_FORM_data1, &Eight);
+ DIEString FooStr(&Eight, "foo");
+ Foo.addValue(dwarf::DW_AT_name, dwarf::DW_FORM_strp, &FooStr);
+
+ DIE *Mem = new DIE(dwarf::DW_TAG_member);
+ DIEString MemStr(&Eight, "mem");
+ Mem->addValue(dwarf::DW_AT_name, dwarf::DW_FORM_strp, &MemStr);
+ DIEInteger Zero(0);
+ Mem->addValue(dwarf::DW_AT_data_member_location, dwarf::DW_FORM_data1, &Zero);
+
+ DIE FooRef(dwarf::DW_TAG_reference_type);
+ FooRef.addValue(dwarf::DW_AT_byte_size, dwarf::DW_FORM_data1, &Eight);
+ DIEEntry FooEntry(&Foo);
+ FooRef.addValue(dwarf::DW_AT_type, dwarf::DW_FORM_ref4, &FooEntry);
+
+ DIE FooRefConst(dwarf::DW_TAG_const_type);
+ DIEEntry FooRefRef(&FooRef);
+ FooRefConst.addValue(dwarf::DW_AT_type, dwarf::DW_FORM_ref4, &FooRefRef);
+
+ DIEEntry FooRefConstRef(&FooRefConst);
+ Mem->addValue(dwarf::DW_AT_type, dwarf::DW_FORM_ref4, &FooRefConstRef);
+
+ Foo.addChild(Mem);
+
+ uint64_t MD5Res = DIEHash().computeTypeSignature(Foo);
+
+ ASSERT_EQ(0xa0b15f467ad4525bULL, MD5Res);
+}
+
+// struct foo { foo &&mem; };
+TEST(DIEHashTest, RValueReference) {
+ DIE Foo(dwarf::DW_TAG_structure_type);
+ DIEInteger Eight(8);
+ Foo.addValue(dwarf::DW_AT_byte_size, dwarf::DW_FORM_data1, &Eight);
+ DIEString FooStr(&Eight, "foo");
+ Foo.addValue(dwarf::DW_AT_name, dwarf::DW_FORM_strp, &FooStr);
+
+ DIE *Mem = new DIE(dwarf::DW_TAG_member);
+ DIEString MemStr(&Eight, "mem");
+ Mem->addValue(dwarf::DW_AT_name, dwarf::DW_FORM_strp, &MemStr);
+ DIEInteger Zero(0);
+ Mem->addValue(dwarf::DW_AT_data_member_location, dwarf::DW_FORM_data1, &Zero);
+
+ DIE FooRef(dwarf::DW_TAG_rvalue_reference_type);
+ FooRef.addValue(dwarf::DW_AT_byte_size, dwarf::DW_FORM_data1, &Eight);
+ DIEEntry FooEntry(&Foo);
+ FooRef.addValue(dwarf::DW_AT_type, dwarf::DW_FORM_ref4, &FooEntry);
+
+ DIE FooRefConst(dwarf::DW_TAG_const_type);
+ DIEEntry FooRefRef(&FooRef);
+ FooRefConst.addValue(dwarf::DW_AT_type, dwarf::DW_FORM_ref4, &FooRefRef);
+
+ DIEEntry FooRefConstRef(&FooRefConst);
+ Mem->addValue(dwarf::DW_AT_type, dwarf::DW_FORM_ref4, &FooRefConstRef);
+
+ Foo.addChild(Mem);
+
+ uint64_t MD5Res = DIEHash().computeTypeSignature(Foo);
+
+ ASSERT_EQ(0xad211c8c3b31e57ULL, MD5Res);
+}
+
+// struct foo { foo foo::*mem; };
+TEST(DIEHashTest, PtrToMember) {
+ DIE Foo(dwarf::DW_TAG_structure_type);
+ DIEInteger Eight(8);
+ Foo.addValue(dwarf::DW_AT_byte_size, dwarf::DW_FORM_data1, &Eight);
+ DIEString FooStr(&Eight, "foo");
+ Foo.addValue(dwarf::DW_AT_name, dwarf::DW_FORM_strp, &FooStr);
+
+ DIE *Mem = new DIE(dwarf::DW_TAG_member);
+ DIEString MemStr(&Eight, "mem");
+ Mem->addValue(dwarf::DW_AT_name, dwarf::DW_FORM_strp, &MemStr);
+ DIEInteger Zero(0);
+ Mem->addValue(dwarf::DW_AT_data_member_location, dwarf::DW_FORM_data1, &Zero);
+
+ DIE PtrToFooMem(dwarf::DW_TAG_ptr_to_member_type);
+ DIEEntry FooEntry(&Foo);
+ PtrToFooMem.addValue(dwarf::DW_AT_type, dwarf::DW_FORM_ref4, &FooEntry);
+ PtrToFooMem.addValue(dwarf::DW_AT_containing_type, dwarf::DW_FORM_ref4, &FooEntry);
+
+ DIEEntry PtrToFooMemRef(&PtrToFooMem);
+ Mem->addValue(dwarf::DW_AT_type, dwarf::DW_FORM_ref4, &PtrToFooMemRef);
+
+ Foo.addChild(Mem);
+
+ uint64_t MD5Res = DIEHash().computeTypeSignature(Foo);
+
+ ASSERT_EQ(0x852e0c9ff7c04ebULL, MD5Res);
+}
+
+// Check that the hash for a pointer-to-member matches regardless of whether the
+// pointed-to type is a declaration or a definition.
+//
+// struct bar; // { };
+// struct foo { bar foo::*mem; };
+TEST(DIEHashTest, PtrToMemberDeclDefMatch) {
+ DIEInteger Zero(0);
+ DIEInteger One(1);
+ DIEInteger Eight(8);
+ DIEString FooStr(&Eight, "foo");
+ DIEString BarStr(&Eight, "bar");
+ DIEString MemStr(&Eight, "mem");
+ uint64_t MD5ResDecl;
+ {
+ DIE Bar(dwarf::DW_TAG_structure_type);
+ Bar.addValue(dwarf::DW_AT_name, dwarf::DW_FORM_strp, &BarStr);
+ Bar.addValue(dwarf::DW_AT_declaration, dwarf::DW_FORM_flag_present, &One);
+
+ DIE Foo(dwarf::DW_TAG_structure_type);
+ Foo.addValue(dwarf::DW_AT_byte_size, dwarf::DW_FORM_data1, &Eight);
+ Foo.addValue(dwarf::DW_AT_name, dwarf::DW_FORM_strp, &FooStr);
+
+ DIE *Mem = new DIE(dwarf::DW_TAG_member);
+ Mem->addValue(dwarf::DW_AT_name, dwarf::DW_FORM_strp, &MemStr);
+ Mem->addValue(dwarf::DW_AT_data_member_location, dwarf::DW_FORM_data1,
+ &Zero);
+
+ DIE PtrToFooMem(dwarf::DW_TAG_ptr_to_member_type);
+ DIEEntry BarEntry(&Bar);
+ PtrToFooMem.addValue(dwarf::DW_AT_type, dwarf::DW_FORM_ref4, &BarEntry);
+ DIEEntry FooEntry(&Foo);
+ PtrToFooMem.addValue(dwarf::DW_AT_containing_type, dwarf::DW_FORM_ref4,
+ &FooEntry);
+
+ DIEEntry PtrToFooMemRef(&PtrToFooMem);
+ Mem->addValue(dwarf::DW_AT_type, dwarf::DW_FORM_ref4, &PtrToFooMemRef);
+
+ Foo.addChild(Mem);
+
+ MD5ResDecl = DIEHash().computeTypeSignature(Foo);
+ }
+ uint64_t MD5ResDef;
+ {
+ DIE Bar(dwarf::DW_TAG_structure_type);
+ Bar.addValue(dwarf::DW_AT_name, dwarf::DW_FORM_strp, &BarStr);
+ Bar.addValue(dwarf::DW_AT_byte_size, dwarf::DW_FORM_data1, &One);
+
+ DIE Foo(dwarf::DW_TAG_structure_type);
+ Foo.addValue(dwarf::DW_AT_byte_size, dwarf::DW_FORM_data1, &Eight);
+ Foo.addValue(dwarf::DW_AT_name, dwarf::DW_FORM_strp, &FooStr);
+
+ DIE *Mem = new DIE(dwarf::DW_TAG_member);
+ Mem->addValue(dwarf::DW_AT_name, dwarf::DW_FORM_strp, &MemStr);
+ Mem->addValue(dwarf::DW_AT_data_member_location, dwarf::DW_FORM_data1,
+ &Zero);
+
+ DIE PtrToFooMem(dwarf::DW_TAG_ptr_to_member_type);
+ DIEEntry BarEntry(&Bar);
+ PtrToFooMem.addValue(dwarf::DW_AT_type, dwarf::DW_FORM_ref4, &BarEntry);
+ DIEEntry FooEntry(&Foo);
+ PtrToFooMem.addValue(dwarf::DW_AT_containing_type, dwarf::DW_FORM_ref4,
+ &FooEntry);
+
+ DIEEntry PtrToFooMemRef(&PtrToFooMem);
+ Mem->addValue(dwarf::DW_AT_type, dwarf::DW_FORM_ref4, &PtrToFooMemRef);
+
+ Foo.addChild(Mem);
+
+ MD5ResDef = DIEHash().computeTypeSignature(Foo);
+ }
+ ASSERT_EQ(MD5ResDef, MD5ResDecl);
+}
+
+// Check that the hash for a pointer-to-member matches regardless of whether the
+// pointed-to type is a declaration or a definition.
+//
+// struct bar; // { };
+// struct foo { bar bar::*mem; };
+TEST(DIEHashTest, PtrToMemberDeclDefMisMatch) {
+ DIEInteger Zero(0);
+ DIEInteger One(1);
+ DIEInteger Eight(8);
+ DIEString FooStr(&Eight, "foo");
+ DIEString BarStr(&Eight, "bar");
+ DIEString MemStr(&Eight, "mem");
+ uint64_t MD5ResDecl;
+ {
+ DIE Bar(dwarf::DW_TAG_structure_type);
+ Bar.addValue(dwarf::DW_AT_name, dwarf::DW_FORM_strp, &BarStr);
+ Bar.addValue(dwarf::DW_AT_declaration, dwarf::DW_FORM_flag_present, &One);
+
+ DIE Foo(dwarf::DW_TAG_structure_type);
+ Foo.addValue(dwarf::DW_AT_byte_size, dwarf::DW_FORM_data1, &Eight);
+ Foo.addValue(dwarf::DW_AT_name, dwarf::DW_FORM_strp, &FooStr);
+
+ DIE *Mem = new DIE(dwarf::DW_TAG_member);
+ Mem->addValue(dwarf::DW_AT_name, dwarf::DW_FORM_strp, &MemStr);
+ Mem->addValue(dwarf::DW_AT_data_member_location, dwarf::DW_FORM_data1,
+ &Zero);
+
+ DIE PtrToFooMem(dwarf::DW_TAG_ptr_to_member_type);
+ DIEEntry BarEntry(&Bar);
+ PtrToFooMem.addValue(dwarf::DW_AT_type, dwarf::DW_FORM_ref4, &BarEntry);
+ PtrToFooMem.addValue(dwarf::DW_AT_containing_type, dwarf::DW_FORM_ref4,
+ &BarEntry);
+
+ DIEEntry PtrToFooMemRef(&PtrToFooMem);
+ Mem->addValue(dwarf::DW_AT_type, dwarf::DW_FORM_ref4, &PtrToFooMemRef);
+
+ Foo.addChild(Mem);
+
+ MD5ResDecl = DIEHash().computeTypeSignature(Foo);
+ }
+ uint64_t MD5ResDef;
+ {
+ DIE Bar(dwarf::DW_TAG_structure_type);
+ Bar.addValue(dwarf::DW_AT_name, dwarf::DW_FORM_strp, &BarStr);
+ Bar.addValue(dwarf::DW_AT_byte_size, dwarf::DW_FORM_data1, &One);
+
+ DIE Foo(dwarf::DW_TAG_structure_type);
+ Foo.addValue(dwarf::DW_AT_byte_size, dwarf::DW_FORM_data1, &Eight);
+ Foo.addValue(dwarf::DW_AT_name, dwarf::DW_FORM_strp, &FooStr);
+
+ DIE *Mem = new DIE(dwarf::DW_TAG_member);
+ Mem->addValue(dwarf::DW_AT_name, dwarf::DW_FORM_strp, &MemStr);
+ Mem->addValue(dwarf::DW_AT_data_member_location, dwarf::DW_FORM_data1,
+ &Zero);
+
+ DIE PtrToFooMem(dwarf::DW_TAG_ptr_to_member_type);
+ DIEEntry BarEntry(&Bar);
+ PtrToFooMem.addValue(dwarf::DW_AT_type, dwarf::DW_FORM_ref4, &BarEntry);
+ PtrToFooMem.addValue(dwarf::DW_AT_containing_type, dwarf::DW_FORM_ref4,
+ &BarEntry);
+
+ DIEEntry PtrToFooMemRef(&PtrToFooMem);
+ Mem->addValue(dwarf::DW_AT_type, dwarf::DW_FORM_ref4, &PtrToFooMemRef);
+
+ Foo.addChild(Mem);
+
+ MD5ResDef = DIEHash().computeTypeSignature(Foo);
+ }
+ // FIXME: This seems to be a bug in the DWARF type hashing specification that
+ // only uses the brief name hashing for types referenced via DW_AT_type. In
+ // this case the type is referenced via DW_AT_containing_type and full hashing
+ // causes a hash to differ when the containing type is a declaration in one TU
+ // and a definition in another.
+ ASSERT_NE(MD5ResDef, MD5ResDecl);
+}
+
+// struct { } a;
+// struct foo { decltype(a) mem; };
+TEST(DIEHashTest, RefUnnamedType) {
+ DIEInteger Zero(0);
+ DIEInteger One(1);
+ DIEInteger Eight(8);
+ DIEString FooStr(&Zero, "foo");
+ DIEString MemStr(&Zero, "mem");
+
+ DIE Unnamed(dwarf::DW_TAG_structure_type);
+ Unnamed.addValue(dwarf::DW_AT_byte_size, dwarf::DW_FORM_data1, &One);
+
+ DIE Foo(dwarf::DW_TAG_structure_type);
+ Foo.addValue(dwarf::DW_AT_byte_size, dwarf::DW_FORM_data1, &Eight);
+ Foo.addValue(dwarf::DW_AT_name, dwarf::DW_FORM_strp, &FooStr);
+
+ DIE *Mem = new DIE(dwarf::DW_TAG_member);
+ Mem->addValue(dwarf::DW_AT_name, dwarf::DW_FORM_strp, &MemStr);
+ Mem->addValue(dwarf::DW_AT_data_member_location, dwarf::DW_FORM_data1, &Zero);
+
+ DIE UnnamedPtr(dwarf::DW_TAG_pointer_type);
+ UnnamedPtr.addValue(dwarf::DW_AT_byte_size, dwarf::DW_FORM_data1, &Eight);
+ DIEEntry UnnamedRef(&Unnamed);
+ UnnamedPtr.addValue(dwarf::DW_AT_type, dwarf::DW_FORM_ref4, &UnnamedRef);
+
+ DIEEntry UnnamedPtrRef(&UnnamedPtr);
+ Mem->addValue(dwarf::DW_AT_type, dwarf::DW_FORM_ref4, &UnnamedPtrRef);
+
+ Foo.addChild(Mem);
+
+ uint64_t MD5Res = DIEHash().computeTypeSignature(Foo);
+
+ ASSERT_EQ(0x954e026f01c02529ULL, MD5Res);
+}
+
+// struct { struct bar { }; };
+TEST(DIEHashTest, NestedType) {
+ DIE Unnamed(dwarf::DW_TAG_structure_type);
+ DIEInteger One(1);
+ Unnamed.addValue(dwarf::DW_AT_byte_size, dwarf::DW_FORM_data1, &One);
+
+ DIE *Foo = new DIE(dwarf::DW_TAG_structure_type);
+ DIEString FooStr(&One, "foo");
+ Foo->addValue(dwarf::DW_AT_name, dwarf::DW_FORM_strp, &FooStr);
+ Foo->addValue(dwarf::DW_AT_byte_size, dwarf::DW_FORM_data1, &One);
+
+ Unnamed.addChild(Foo);
+
+ uint64_t MD5Res = DIEHash().computeTypeSignature(Unnamed);
+
+ // The exact same hash GCC produces for this DIE.
+ ASSERT_EQ(0xde8a3b7b43807f4aULL, MD5Res);
+}
+
+// struct { static void func(); };
+TEST(DIEHashTest, MemberFunc) {
+ DIE Unnamed(dwarf::DW_TAG_structure_type);
+ DIEInteger One(1);
+ Unnamed.addValue(dwarf::DW_AT_byte_size, dwarf::DW_FORM_data1, &One);
+
+ DIE *Func = new DIE(dwarf::DW_TAG_subprogram);
+ DIEString FuncStr(&One, "func");
+ Func->addValue(dwarf::DW_AT_name, dwarf::DW_FORM_strp, &FuncStr);
+
+ Unnamed.addChild(Func);
+
+ uint64_t MD5Res = DIEHash().computeTypeSignature(Unnamed);
+
+ // The exact same hash GCC produces for this DIE.
+ ASSERT_EQ(0xd36a1b6dfb604ba0ULL, MD5Res);
+}
+}
diff --git a/unittests/CodeGen/Makefile b/unittests/CodeGen/Makefile
new file mode 100644
index 0000000..4f07017
--- /dev/null
+++ b/unittests/CodeGen/Makefile
@@ -0,0 +1,16 @@
+##===- unittests/DebugInfo/Makefile ------------------------*- Makefile -*-===##
+#
+# The LLVM Compiler Infrastructure
+#
+# This file is distributed under the University of Illinois Open Source
+# License. See LICENSE.TXT for details.
+#
+##===----------------------------------------------------------------------===##
+
+LEVEL = ../..
+TESTNAME = CodeGen
+LINK_COMPONENTS := asmprinter codegen support
+
+include $(LEVEL)/Makefile.config
+
+include $(LLVM_SRC_ROOT)/unittests/Makefile.unittest
diff --git a/unittests/DebugInfo/DWARFFormValueTest.cpp b/unittests/DebugInfo/DWARFFormValueTest.cpp
index 04b859b..38b932e 100644
--- a/unittests/DebugInfo/DWARFFormValueTest.cpp
+++ b/unittests/DebugInfo/DWARFFormValueTest.cpp
@@ -18,14 +18,32 @@ namespace {
TEST(DWARFFormValue, FixedFormSizes) {
// Size of DW_FORM_addr and DW_FORM_ref_addr are equal in DWARF2,
// DW_FORM_ref_addr is always 4 bytes in DWARF32 starting from DWARF3.
- const uint8_t *sizes = DWARFFormValue::getFixedFormSizes(4, 2);
+ ArrayRef<uint8_t> sizes = DWARFFormValue::getFixedFormSizes(4, 2);
EXPECT_EQ(sizes[DW_FORM_addr], sizes[DW_FORM_ref_addr]);
sizes = DWARFFormValue::getFixedFormSizes(8, 2);
EXPECT_EQ(sizes[DW_FORM_addr], sizes[DW_FORM_ref_addr]);
sizes = DWARFFormValue::getFixedFormSizes(8, 3);
EXPECT_EQ(4, sizes[DW_FORM_ref_addr]);
// Check that we don't have fixed form sizes for weird address sizes.
- EXPECT_EQ(0, DWARFFormValue::getFixedFormSizes(16, 2));
+ EXPECT_EQ(0U, DWARFFormValue::getFixedFormSizes(16, 2).size());
+}
+
+bool isFormClass(uint16_t Form, DWARFFormValue::FormClass FC) {
+ return DWARFFormValue(Form).isFormClass(FC);
+}
+
+TEST(DWARFFormValue, FormClass) {
+ EXPECT_TRUE(isFormClass(DW_FORM_addr, DWARFFormValue::FC_Address));
+ EXPECT_FALSE(isFormClass(DW_FORM_data8, DWARFFormValue::FC_Address));
+ EXPECT_TRUE(isFormClass(DW_FORM_data8, DWARFFormValue::FC_Constant));
+ EXPECT_TRUE(isFormClass(DW_FORM_data8, DWARFFormValue::FC_SectionOffset));
+ EXPECT_TRUE(
+ isFormClass(DW_FORM_sec_offset, DWARFFormValue::FC_SectionOffset));
+ EXPECT_TRUE(isFormClass(DW_FORM_GNU_str_index, DWARFFormValue::FC_String));
+ EXPECT_TRUE(isFormClass(DW_FORM_GNU_addr_index, DWARFFormValue::FC_Address));
+ EXPECT_FALSE(isFormClass(DW_FORM_ref_addr, DWARFFormValue::FC_Address));
+ EXPECT_TRUE(isFormClass(DW_FORM_ref_addr, DWARFFormValue::FC_Reference));
+ EXPECT_TRUE(isFormClass(DW_FORM_ref_sig8, DWARFFormValue::FC_Reference));
}
} // end anonymous namespace
diff --git a/unittests/ExecutionEngine/JIT/JITMemoryManagerTest.cpp b/unittests/ExecutionEngine/JIT/JITMemoryManagerTest.cpp
index 68ca53d..731f780 100644
--- a/unittests/ExecutionEngine/JIT/JITMemoryManagerTest.cpp
+++ b/unittests/ExecutionEngine/JIT/JITMemoryManagerTest.cpp
@@ -281,11 +281,11 @@ TEST(JITMemoryManagerTest, TestManyStubs) {
TEST(JITMemoryManagerTest, AllocateSection) {
OwningPtr<JITMemoryManager> MemMgr(
JITMemoryManager::CreateDefaultMemManager());
- uint8_t *code1 = MemMgr->allocateCodeSection(256, 0, 1);
- uint8_t *data1 = MemMgr->allocateDataSection(256, 16, 2, true);
- uint8_t *code2 = MemMgr->allocateCodeSection(257, 32, 3);
- uint8_t *data2 = MemMgr->allocateDataSection(256, 64, 4, false);
- uint8_t *code3 = MemMgr->allocateCodeSection(258, 64, 5);
+ uint8_t *code1 = MemMgr->allocateCodeSection(256, 0, 1, StringRef());
+ uint8_t *data1 = MemMgr->allocateDataSection(256, 16, 2, StringRef(), true);
+ uint8_t *code2 = MemMgr->allocateCodeSection(257, 32, 3, StringRef());
+ uint8_t *data2 = MemMgr->allocateDataSection(256, 64, 4, StringRef(), false);
+ uint8_t *code3 = MemMgr->allocateCodeSection(258, 64, 5, StringRef());
EXPECT_NE((uint8_t*)0, code1);
EXPECT_NE((uint8_t*)0, code2);
diff --git a/unittests/ExecutionEngine/JIT/JITTest.cpp b/unittests/ExecutionEngine/JIT/JITTest.cpp
index 3b94d76..4c7b1e2 100644
--- a/unittests/ExecutionEngine/JIT/JITTest.cpp
+++ b/unittests/ExecutionEngine/JIT/JITTest.cpp
@@ -135,13 +135,17 @@ public:
EndFunctionBodyCall(F, FunctionStart, FunctionEnd));
Base->endFunctionBody(F, FunctionStart, FunctionEnd);
}
- virtual uint8_t *allocateDataSection(uintptr_t Size, unsigned Alignment,
- unsigned SectionID, bool IsReadOnly) {
- return Base->allocateDataSection(Size, Alignment, SectionID, IsReadOnly);
+ virtual uint8_t *allocateDataSection(
+ uintptr_t Size, unsigned Alignment, unsigned SectionID,
+ StringRef SectionName, bool IsReadOnly) {
+ return Base->allocateDataSection(
+ Size, Alignment, SectionID, SectionName, IsReadOnly);
}
- virtual uint8_t *allocateCodeSection(uintptr_t Size, unsigned Alignment,
- unsigned SectionID) {
- return Base->allocateCodeSection(Size, Alignment, SectionID);
+ virtual uint8_t *allocateCodeSection(
+ uintptr_t Size, unsigned Alignment, unsigned SectionID,
+ StringRef SectionName) {
+ return Base->allocateCodeSection(
+ Size, Alignment, SectionID, SectionName);
}
virtual bool finalizeMemory(std::string *ErrMsg) { return false; }
virtual uint8_t *allocateSpace(intptr_t Size, unsigned Alignment) {
@@ -717,16 +721,4 @@ TEST(LazyLoadedJITTest, EagerCompiledRecursionThroughGhost) {
}
#endif // !defined(__arm__) && !defined(__powerpc__) && !defined(__s390__)
-// 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.
-class JITEnvironment : public testing::Environment {
- virtual void SetUp() {
- // Required to create a JIT.
- InitializeNativeTarget();
- }
-};
-testing::Environment* const jit_env =
- testing::AddGlobalTestEnvironment(new JITEnvironment);
-
}
diff --git a/unittests/ExecutionEngine/MCJIT/CMakeLists.txt b/unittests/ExecutionEngine/MCJIT/CMakeLists.txt
index 922cb7e..ed43099 100644
--- a/unittests/ExecutionEngine/MCJIT/CMakeLists.txt
+++ b/unittests/ExecutionEngine/MCJIT/CMakeLists.txt
@@ -2,7 +2,6 @@ set(LLVM_LINK_COMPONENTS
asmparser
bitreader
bitwriter
- jit
mcjit
nativecodegen
)
@@ -11,6 +10,7 @@ set(MCJITTestsSources
MCJITTest.cpp
MCJITCAPITest.cpp
MCJITMemoryManagerTest.cpp
+ MCJITMultipleModuleTest.cpp
MCJITObjectCacheTest.cpp
)
diff --git a/unittests/ExecutionEngine/MCJIT/MCJITCAPITest.cpp b/unittests/ExecutionEngine/MCJIT/MCJITCAPITest.cpp
index c434a7c..46d6d9b 100644
--- a/unittests/ExecutionEngine/MCJIT/MCJITCAPITest.cpp
+++ b/unittests/ExecutionEngine/MCJIT/MCJITCAPITest.cpp
@@ -28,18 +28,20 @@ static bool didCallAllocateCodeSection;
static uint8_t *roundTripAllocateCodeSection(void *object, uintptr_t size,
unsigned alignment,
- unsigned sectionID) {
+ unsigned sectionID,
+ const char *sectionName) {
didCallAllocateCodeSection = true;
return static_cast<SectionMemoryManager*>(object)->allocateCodeSection(
- size, alignment, sectionID);
+ size, alignment, sectionID, sectionName);
}
static uint8_t *roundTripAllocateDataSection(void *object, uintptr_t size,
unsigned alignment,
unsigned sectionID,
+ const char *sectionName,
LLVMBool isReadOnly) {
return static_cast<SectionMemoryManager*>(object)->allocateDataSection(
- size, alignment, sectionID, isReadOnly);
+ size, alignment, sectionID, sectionName, isReadOnly);
}
static LLVMBool roundTripFinalizeMemory(void *object, char **errMsg) {
@@ -57,6 +59,7 @@ static void roundTripDestroy(void *object) {
delete static_cast<SectionMemoryManager*>(object);
}
+namespace {
class MCJITCAPITest : public testing::Test, public MCJITTestAPICommon {
protected:
MCJITCAPITest() {
@@ -154,6 +157,7 @@ protected:
LLVMExecutionEngineRef Engine;
char *Error;
};
+} // end anonymous namespace
TEST_F(MCJITCAPITest, simple_function) {
SKIP_UNSUPPORTED_PLATFORM;
diff --git a/unittests/ExecutionEngine/MCJIT/MCJITMemoryManagerTest.cpp b/unittests/ExecutionEngine/MCJIT/MCJITMemoryManagerTest.cpp
index f6dbf98..c24346d 100644
--- a/unittests/ExecutionEngine/MCJIT/MCJITMemoryManagerTest.cpp
+++ b/unittests/ExecutionEngine/MCJIT/MCJITMemoryManagerTest.cpp
@@ -19,10 +19,10 @@ namespace {
TEST(MCJITMemoryManagerTest, BasicAllocations) {
OwningPtr<SectionMemoryManager> MemMgr(new SectionMemoryManager());
- uint8_t *code1 = MemMgr->allocateCodeSection(256, 0, 1);
- uint8_t *data1 = MemMgr->allocateDataSection(256, 0, 2, true);
- uint8_t *code2 = MemMgr->allocateCodeSection(256, 0, 3);
- uint8_t *data2 = MemMgr->allocateDataSection(256, 0, 4, false);
+ uint8_t *code1 = MemMgr->allocateCodeSection(256, 0, 1, "");
+ uint8_t *data1 = MemMgr->allocateDataSection(256, 0, 2, "", true);
+ uint8_t *code2 = MemMgr->allocateCodeSection(256, 0, 3, "");
+ uint8_t *data2 = MemMgr->allocateDataSection(256, 0, 4, "", false);
EXPECT_NE((uint8_t*)0, code1);
EXPECT_NE((uint8_t*)0, code2);
@@ -52,10 +52,10 @@ TEST(MCJITMemoryManagerTest, BasicAllocations) {
TEST(MCJITMemoryManagerTest, LargeAllocations) {
OwningPtr<SectionMemoryManager> MemMgr(new SectionMemoryManager());
- uint8_t *code1 = MemMgr->allocateCodeSection(0x100000, 0, 1);
- uint8_t *data1 = MemMgr->allocateDataSection(0x100000, 0, 2, true);
- uint8_t *code2 = MemMgr->allocateCodeSection(0x100000, 0, 3);
- uint8_t *data2 = MemMgr->allocateDataSection(0x100000, 0, 4, false);
+ uint8_t *code1 = MemMgr->allocateCodeSection(0x100000, 0, 1, "");
+ uint8_t *data1 = MemMgr->allocateDataSection(0x100000, 0, 2, "", true);
+ uint8_t *code2 = MemMgr->allocateCodeSection(0x100000, 0, 3, "");
+ uint8_t *data2 = MemMgr->allocateDataSection(0x100000, 0, 4, "", false);
EXPECT_NE((uint8_t*)0, code1);
EXPECT_NE((uint8_t*)0, code2);
@@ -91,8 +91,8 @@ TEST(MCJITMemoryManagerTest, ManyAllocations) {
for (unsigned i = 0; i < 10000; ++i) {
const bool isReadOnly = i % 2 == 0;
- code[i] = MemMgr->allocateCodeSection(32, 0, 1);
- data[i] = MemMgr->allocateDataSection(32, 0, 2, isReadOnly);
+ code[i] = MemMgr->allocateCodeSection(32, 0, 1, "");
+ data[i] = MemMgr->allocateDataSection(32, 0, 2, "", isReadOnly);
for (unsigned j = 0; j < 32; j++) {
code[i][j] = 1 + (i % 254);
@@ -130,8 +130,8 @@ TEST(MCJITMemoryManagerTest, ManyVariedAllocations) {
bool isReadOnly = i % 3 == 0;
unsigned Align = 8 << (i % 4);
- code[i] = MemMgr->allocateCodeSection(CodeSize, Align, i);
- data[i] = MemMgr->allocateDataSection(DataSize, Align, i + 10000,
+ code[i] = MemMgr->allocateCodeSection(CodeSize, Align, i, "");
+ data[i] = MemMgr->allocateDataSection(DataSize, Align, i + 10000, "",
isReadOnly);
for (unsigned j = 0; j < CodeSize; j++) {
diff --git a/unittests/ExecutionEngine/MCJIT/MCJITMultipleModuleTest.cpp b/unittests/ExecutionEngine/MCJIT/MCJITMultipleModuleTest.cpp
new file mode 100644
index 0000000..7c3239e
--- /dev/null
+++ b/unittests/ExecutionEngine/MCJIT/MCJITMultipleModuleTest.cpp
@@ -0,0 +1,395 @@
+//===- MCJITMultipeModuleTest.cpp - Unit tests for the MCJIT---------------===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// This test suite verifies MCJIT for handling multiple modules in a single
+// ExecutionEngine by building multiple modules, making function calls across
+// modules, accessing global variables, etc.
+//===----------------------------------------------------------------------===//
+
+#include "llvm/ExecutionEngine/MCJIT.h"
+#include "MCJITTestBase.h"
+#include "gtest/gtest.h"
+
+using namespace llvm;
+
+namespace {
+
+class MCJITMultipleModuleTest : public testing::Test, public MCJITTestBase {};
+
+// FIXME: ExecutionEngine has no support empty modules
+/*
+TEST_F(MCJITMultipleModuleTest, multiple_empty_modules) {
+ SKIP_UNSUPPORTED_PLATFORM;
+
+ createJIT(M.take());
+ // JIT-compile
+ EXPECT_NE(0, TheJIT->getObjectImage())
+ << "Unable to generate executable loaded object image";
+
+ TheJIT->addModule(createEmptyModule("<other module>"));
+ TheJIT->addModule(createEmptyModule("<other other module>"));
+
+ // JIT again
+ EXPECT_NE(0, TheJIT->getObjectImage())
+ << "Unable to generate executable loaded object image";
+}
+*/
+
+// Helper Function to test add operation
+void checkAdd(uint64_t ptr) {
+ ASSERT_TRUE(ptr != 0) << "Unable to get pointer to function.";
+ int (*AddPtr)(int, int) = (int (*)(int, int))ptr;
+ EXPECT_EQ(0, AddPtr(0, 0));
+ EXPECT_EQ(1, AddPtr(1, 0));
+ EXPECT_EQ(3, AddPtr(1, 2));
+ EXPECT_EQ(-5, AddPtr(-2, -3));
+ EXPECT_EQ(30, AddPtr(10, 20));
+ EXPECT_EQ(-30, AddPtr(-10, -20));
+ EXPECT_EQ(-40, AddPtr(-10, -30));
+}
+
+void checkAccumulate(uint64_t ptr) {
+ ASSERT_TRUE(ptr != 0) << "Unable to get pointer to function.";
+ int32_t (*FPtr)(int32_t) = (int32_t (*)(int32_t))(intptr_t)ptr;
+ EXPECT_EQ(0, FPtr(0));
+ EXPECT_EQ(1, FPtr(1));
+ EXPECT_EQ(3, FPtr(2));
+ EXPECT_EQ(6, FPtr(3));
+ EXPECT_EQ(10, FPtr(4));
+ EXPECT_EQ(15, FPtr(5));
+}
+
+// FIXME: ExecutionEngine has no support empty modules
+/*
+TEST_F(MCJITMultipleModuleTest, multiple_empty_modules) {
+ SKIP_UNSUPPORTED_PLATFORM;
+
+ createJIT(M.take());
+ // JIT-compile
+ EXPECT_NE(0, TheJIT->getObjectImage())
+ << "Unable to generate executable loaded object image";
+
+ TheJIT->addModule(createEmptyModule("<other module>"));
+ TheJIT->addModule(createEmptyModule("<other other module>"));
+
+ // JIT again
+ EXPECT_NE(0, TheJIT->getObjectImage())
+ << "Unable to generate executable loaded object image";
+}
+*/
+
+// Module A { Function FA },
+// Module B { Function FB },
+// execute FA then FB
+TEST_F(MCJITMultipleModuleTest, two_module_case) {
+ SKIP_UNSUPPORTED_PLATFORM;
+
+ OwningPtr<Module> A, B;
+ Function *FA, *FB;
+ createTwoModuleCase(A, FA, B, FB);
+
+ createJIT(A.take());
+ TheJIT->addModule(B.take());
+
+ uint64_t ptr = TheJIT->getFunctionAddress(FA->getName().str());
+ checkAdd(ptr);
+
+ ptr = TheJIT->getFunctionAddress(FB->getName().str());
+ checkAdd(ptr);
+}
+
+// Module A { Function FA },
+// Module B { Function FB },
+// execute FB then FA
+TEST_F(MCJITMultipleModuleTest, two_module_reverse_case) {
+ SKIP_UNSUPPORTED_PLATFORM;
+
+ OwningPtr<Module> A, B;
+ Function *FA, *FB;
+ createTwoModuleCase(A, FA, B, FB);
+
+ createJIT(A.take());
+ TheJIT->addModule(B.take());
+
+ uint64_t ptr = TheJIT->getFunctionAddress(FB->getName().str());
+ TheJIT->finalizeObject();
+ checkAdd(ptr);
+
+ ptr = TheJIT->getFunctionAddress(FA->getName().str());
+ checkAdd(ptr);
+}
+
+// Module A { Function FA },
+// Module B { Extern FA, Function FB which calls FA },
+// execute FB then FA
+TEST_F(MCJITMultipleModuleTest, two_module_extern_reverse_case) {
+ SKIP_UNSUPPORTED_PLATFORM;
+
+ OwningPtr<Module> A, B;
+ Function *FA, *FB;
+ createTwoModuleExternCase(A, FA, B, FB);
+
+ createJIT(A.take());
+ TheJIT->addModule(B.take());
+
+ uint64_t ptr = TheJIT->getFunctionAddress(FB->getName().str());
+ TheJIT->finalizeObject();
+ checkAdd(ptr);
+
+ ptr = TheJIT->getFunctionAddress(FA->getName().str());
+ checkAdd(ptr);
+}
+
+// Module A { Function FA },
+// Module B { Extern FA, Function FB which calls FA },
+// execute FA then FB
+TEST_F(MCJITMultipleModuleTest, two_module_extern_case) {
+ SKIP_UNSUPPORTED_PLATFORM;
+
+ OwningPtr<Module> A, B;
+ Function *FA, *FB;
+ createTwoModuleExternCase(A, FA, B, FB);
+
+ createJIT(A.take());
+ TheJIT->addModule(B.take());
+
+ uint64_t ptr = TheJIT->getFunctionAddress(FA->getName().str());
+ checkAdd(ptr);
+
+ ptr = TheJIT->getFunctionAddress(FB->getName().str());
+ checkAdd(ptr);
+}
+
+// Module A { Function FA1, Function FA2 which calls FA1 },
+// Module B { Extern FA1, Function FB which calls FA1 },
+// execute FB then FA2
+TEST_F(MCJITMultipleModuleTest, two_module_consecutive_call_case) {
+ SKIP_UNSUPPORTED_PLATFORM;
+
+ OwningPtr<Module> A, B;
+ Function *FA1, *FA2, *FB;
+ createTwoModuleExternCase(A, FA1, B, FB);
+ FA2 = insertSimpleCallFunction<int32_t(int32_t, int32_t)>(A.get(), FA1);
+
+ createJIT(A.take());
+ TheJIT->addModule(B.take());
+
+ uint64_t ptr = TheJIT->getFunctionAddress(FB->getName().str());
+ TheJIT->finalizeObject();
+ checkAdd(ptr);
+
+ ptr = TheJIT->getFunctionAddress(FA2->getName().str());
+ checkAdd(ptr);
+}
+
+// TODO:
+// Module A { Extern Global GVB, Global Variable GVA, Function FA loads GVB },
+// Module B { Extern Global GVA, Global Variable GVB, Function FB loads GVA },
+
+
+// Module A { Global Variable GVA, Function FA loads GVA },
+// Module B { Global Variable GVB, Function FB loads GVB },
+// execute FB then FA
+TEST_F(MCJITMultipleModuleTest, two_module_global_variables_case) {
+ SKIP_UNSUPPORTED_PLATFORM;
+
+ OwningPtr<Module> A, B;
+ Function *FA, *FB;
+ GlobalVariable *GVA, *GVB;
+ A.reset(createEmptyModule("A"));
+ B.reset(createEmptyModule("B"));
+
+ int32_t initialNum = 7;
+ GVA = insertGlobalInt32(A.get(), "GVA", initialNum);
+ GVB = insertGlobalInt32(B.get(), "GVB", initialNum);
+ FA = startFunction<int32_t(void)>(A.get(), "FA");
+ endFunctionWithRet(FA, Builder.CreateLoad(GVA));
+ FB = startFunction<int32_t(void)>(B.get(), "FB");
+ endFunctionWithRet(FB, Builder.CreateLoad(GVB));
+
+ createJIT(A.take());
+ TheJIT->addModule(B.take());
+
+ uint64_t FBPtr = TheJIT->getFunctionAddress(FB->getName().str());
+ TheJIT->finalizeObject();
+ EXPECT_TRUE(0 != FBPtr);
+ int32_t(*FuncPtr)(void) = (int32_t(*)(void))FBPtr;
+ EXPECT_EQ(initialNum, FuncPtr())
+ << "Invalid value for global returned from JITted function in module B";
+
+ uint64_t FAPtr = TheJIT->getFunctionAddress(FA->getName().str());
+ EXPECT_TRUE(0 != FAPtr);
+ FuncPtr = (int32_t(*)(void))FAPtr;
+ EXPECT_EQ(initialNum, FuncPtr())
+ << "Invalid value for global returned from JITted function in module A";
+}
+
+// Module A { Function FA },
+// Module B { Extern FA, Function FB which calls FA },
+// Module C { Extern FA, Function FC which calls FA },
+// execute FC, FB, FA
+TEST_F(MCJITMultipleModuleTest, three_module_case) {
+ SKIP_UNSUPPORTED_PLATFORM;
+
+ OwningPtr<Module> A, B, C;
+ Function *FA, *FB, *FC;
+ createThreeModuleCase(A, FA, B, FB, C, FC);
+
+ createJIT(A.take());
+ TheJIT->addModule(B.take());
+ TheJIT->addModule(C.take());
+
+ uint64_t ptr = TheJIT->getFunctionAddress(FC->getName().str());
+ checkAdd(ptr);
+
+ ptr = TheJIT->getFunctionAddress(FB->getName().str());
+ checkAdd(ptr);
+
+ ptr = TheJIT->getFunctionAddress(FA->getName().str());
+ checkAdd(ptr);
+}
+
+// Module A { Function FA },
+// Module B { Extern FA, Function FB which calls FA },
+// Module C { Extern FA, Function FC which calls FA },
+// execute FA, FB, FC
+TEST_F(MCJITMultipleModuleTest, three_module_case_reverse_order) {
+ SKIP_UNSUPPORTED_PLATFORM;
+
+ OwningPtr<Module> A, B, C;
+ Function *FA, *FB, *FC;
+ createThreeModuleCase(A, FA, B, FB, C, FC);
+
+ createJIT(A.take());
+ TheJIT->addModule(B.take());
+ TheJIT->addModule(C.take());
+
+ uint64_t ptr = TheJIT->getFunctionAddress(FA->getName().str());
+ checkAdd(ptr);
+
+ ptr = TheJIT->getFunctionAddress(FB->getName().str());
+ checkAdd(ptr);
+
+ ptr = TheJIT->getFunctionAddress(FC->getName().str());
+ checkAdd(ptr);
+}
+
+// Module A { Function FA },
+// Module B { Extern FA, Function FB which calls FA },
+// Module C { Extern FB, Function FC which calls FB },
+// execute FC, FB, FA
+TEST_F(MCJITMultipleModuleTest, three_module_chain_case) {
+ SKIP_UNSUPPORTED_PLATFORM;
+
+ OwningPtr<Module> A, B, C;
+ Function *FA, *FB, *FC;
+ createThreeModuleChainedCallsCase(A, FA, B, FB, C, FC);
+
+ createJIT(A.take());
+ TheJIT->addModule(B.take());
+ TheJIT->addModule(C.take());
+
+ uint64_t ptr = TheJIT->getFunctionAddress(FC->getName().str());
+ checkAdd(ptr);
+
+ ptr = TheJIT->getFunctionAddress(FB->getName().str());
+ checkAdd(ptr);
+
+ ptr = TheJIT->getFunctionAddress(FA->getName().str());
+ checkAdd(ptr);
+}
+
+// Module A { Function FA },
+// Module B { Extern FA, Function FB which calls FA },
+// Module C { Extern FB, Function FC which calls FB },
+// execute FA, FB, FC
+TEST_F(MCJITMultipleModuleTest, three_modules_chain_case_reverse_order) {
+ SKIP_UNSUPPORTED_PLATFORM;
+
+ OwningPtr<Module> A, B, C;
+ Function *FA, *FB, *FC;
+ createThreeModuleChainedCallsCase(A, FA, B, FB, C, FC);
+
+ createJIT(A.take());
+ TheJIT->addModule(B.take());
+ TheJIT->addModule(C.take());
+
+ uint64_t ptr = TheJIT->getFunctionAddress(FA->getName().str());
+ checkAdd(ptr);
+
+ ptr = TheJIT->getFunctionAddress(FB->getName().str());
+ checkAdd(ptr);
+
+ ptr = TheJIT->getFunctionAddress(FC->getName().str());
+ checkAdd(ptr);
+}
+
+// Module A { Extern FB, Function FA which calls FB1 },
+// Module B { Extern FA, Function FB1, Function FB2 which calls FA },
+// execute FA, then FB1
+// FIXME: this test case is not supported by MCJIT
+TEST_F(MCJITMultipleModuleTest, cross_module_dependency_case) {
+ SKIP_UNSUPPORTED_PLATFORM;
+
+ OwningPtr<Module> A, B;
+ Function *FA, *FB1, *FB2;
+ createCrossModuleRecursiveCase(A, FA, B, FB1, FB2);
+
+ createJIT(A.take());
+ TheJIT->addModule(B.take());
+
+ uint64_t ptr = TheJIT->getFunctionAddress(FA->getName().str());
+ checkAccumulate(ptr);
+
+ ptr = TheJIT->getFunctionAddress(FB1->getName().str());
+ checkAccumulate(ptr);
+}
+
+// Module A { Extern FB, Function FA which calls FB1 },
+// Module B { Extern FA, Function FB1, Function FB2 which calls FA },
+// execute FB1 then FA
+// FIXME: this test case is not supported by MCJIT
+TEST_F(MCJITMultipleModuleTest, cross_module_dependency_case_reverse_order) {
+ SKIP_UNSUPPORTED_PLATFORM;
+
+ OwningPtr<Module> A, B;
+ Function *FA, *FB1, *FB2;
+ createCrossModuleRecursiveCase(A, FA, B, FB1, FB2);
+
+ createJIT(A.take());
+ TheJIT->addModule(B.take());
+
+ uint64_t ptr = TheJIT->getFunctionAddress(FB1->getName().str());
+ checkAccumulate(ptr);
+
+ ptr = TheJIT->getFunctionAddress(FA->getName().str());
+ checkAccumulate(ptr);
+}
+
+// Module A { Extern FB1, Function FA which calls FB1 },
+// Module B { Extern FA, Function FB1, Function FB2 which calls FA },
+// execute FB1 then FB2
+// FIXME: this test case is not supported by MCJIT
+TEST_F(MCJITMultipleModuleTest, cross_module_dependency_case3) {
+ SKIP_UNSUPPORTED_PLATFORM;
+
+ OwningPtr<Module> A, B;
+ Function *FA, *FB1, *FB2;
+ createCrossModuleRecursiveCase(A, FA, B, FB1, FB2);
+
+ createJIT(A.take());
+ TheJIT->addModule(B.take());
+
+ uint64_t ptr = TheJIT->getFunctionAddress(FB1->getName().str());
+ checkAccumulate(ptr);
+
+ ptr = TheJIT->getFunctionAddress(FB2->getName().str());
+ checkAccumulate(ptr);
+}
+}
diff --git a/unittests/ExecutionEngine/MCJIT/MCJITTest.cpp b/unittests/ExecutionEngine/MCJIT/MCJITTest.cpp
index 43a8298..fab8155 100644
--- a/unittests/ExecutionEngine/MCJIT/MCJITTest.cpp
+++ b/unittests/ExecutionEngine/MCJIT/MCJITTest.cpp
@@ -18,23 +18,27 @@
using namespace llvm;
+namespace {
+
class MCJITTest : public testing::Test, public MCJITTestBase {
protected:
-
- virtual void SetUp() {
- M.reset(createEmptyModule("<main>"));
- }
+ virtual void SetUp() { M.reset(createEmptyModule("<main>")); }
};
-namespace {
+// FIXME: Ensure creating an execution engine does not crash when constructed
+// with a null module.
+/*
+TEST_F(MCJITTest, null_module) {
+ createJIT(0);
+}
+*/
// FIXME: In order to JIT an empty module, there needs to be
// an interface to ExecutionEngine that forces compilation but
-// does require retrieval of a pointer to a function/global.
+// does not require retrieval of a pointer to a function/global.
/*
TEST_F(MCJITTest, empty_module) {
createJIT(M.take());
- TheJIT->finalizeObject();
//EXPECT_NE(0, TheJIT->getObjectImage())
// << "Unable to generate executable loaded object image";
}
@@ -47,7 +51,6 @@ TEST_F(MCJITTest, global_variable) {
GlobalValue *Global = insertGlobalInt32(M.get(), "test_global", initialValue);
createJIT(M.take());
void *globalPtr = TheJIT->getPointerToGlobal(Global);
- TheJIT->finalizeObject();
EXPECT_TRUE(0 != globalPtr)
<< "Unable to get pointer to global value from JIT";
@@ -60,15 +63,19 @@ TEST_F(MCJITTest, add_function) {
Function *F = insertAddFunction(M.get());
createJIT(M.take());
- void *addPtr = TheJIT->getPointerToFunction(F);
- TheJIT->finalizeObject();
+ uint64_t addPtr = TheJIT->getFunctionAddress(F->getName().str());
EXPECT_TRUE(0 != addPtr)
<< "Unable to get pointer to function from JIT";
- int (*AddPtrTy)(int, int) = (int(*)(int, int))(intptr_t)addPtr;
- EXPECT_EQ(0, AddPtrTy(0, 0));
- EXPECT_EQ(3, AddPtrTy(1, 2));
- EXPECT_EQ(-5, AddPtrTy(-2, -3));
+ ASSERT_TRUE(addPtr != 0) << "Unable to get pointer to function .";
+ int (*AddPtr)(int, int) = (int(*)(int, int))addPtr ;
+ EXPECT_EQ(0, AddPtr(0, 0));
+ EXPECT_EQ(1, AddPtr(1, 0));
+ EXPECT_EQ(3, AddPtr(1, 2));
+ EXPECT_EQ(-5, AddPtr(-2, -3));
+ EXPECT_EQ(30, AddPtr(10, 20));
+ EXPECT_EQ(-30, AddPtr(-10, -20));
+ EXPECT_EQ(-40, AddPtr(-10, -30));
}
TEST_F(MCJITTest, run_main) {
@@ -77,12 +84,11 @@ TEST_F(MCJITTest, run_main) {
int rc = 6;
Function *Main = insertMainFunction(M.get(), 6);
createJIT(M.take());
- void *vPtr = TheJIT->getPointerToFunction(Main);
- TheJIT->finalizeObject();
- EXPECT_TRUE(0 != vPtr)
+ uint64_t ptr = TheJIT->getFunctionAddress(Main->getName().str());
+ EXPECT_TRUE(0 != ptr)
<< "Unable to get pointer to main() from JIT";
- int (*FuncPtr)(void) = (int(*)(void))(intptr_t)vPtr;
+ int (*FuncPtr)(void) = (int(*)(void))ptr;
int returnCode = FuncPtr();
EXPECT_EQ(returnCode, rc);
}
@@ -99,11 +105,10 @@ TEST_F(MCJITTest, return_global) {
endFunctionWithRet(ReturnGlobal, ReadGlobal);
createJIT(M.take());
- void *rgvPtr = TheJIT->getPointerToFunction(ReturnGlobal);
- TheJIT->finalizeObject();
+ uint64_t rgvPtr = TheJIT->getFunctionAddress(ReturnGlobal->getName().str());
EXPECT_TRUE(0 != rgvPtr);
- int32_t(*FuncPtr)(void) = (int32_t(*)(void))(intptr_t)rgvPtr;
+ int32_t(*FuncPtr)(void) = (int32_t(*)(void))rgvPtr;
EXPECT_EQ(initialNum, FuncPtr())
<< "Invalid value for global returned from JITted function";
}
@@ -131,10 +136,9 @@ TEST_F(MCJITTest, increment_global) {
createJIT(M.take());
void *gvPtr = TheJIT->getPointerToGlobal(GV);
- TheJIT->finalizeObject();
EXPECT_EQ(initialNum, *(int32_t*)gvPtr);
- void *vPtr = TheJIT->getPointerToFunction(IncrementGlobal);
+ void *vPtr = TheJIT->getFunctionAddress(IncrementGlobal->getName().str());
EXPECT_TRUE(0 != vPtr)
<< "Unable to get pointer to main() from JIT";
@@ -172,67 +176,15 @@ TEST_F(MCJITTest, multiple_functions) {
}
createJIT(M.take());
- void *vPtr = TheJIT->getPointerToFunction(Outer);
- TheJIT->finalizeObject();
- EXPECT_TRUE(0 != vPtr)
+ uint64_t ptr = TheJIT->getFunctionAddress(Outer->getName().str());
+ EXPECT_TRUE(0 != ptr)
<< "Unable to get pointer to outer function from JIT";
- int32_t(*FuncPtr)(void) = (int32_t(*)(void))(intptr_t)vPtr;
+ int32_t(*FuncPtr)(void) = (int32_t(*)(void))ptr;
EXPECT_EQ(innerRetVal, FuncPtr())
<< "Incorrect result returned from function";
}
#endif /*!defined(__arm__)*/
-// FIXME: ExecutionEngine has no support empty modules
-/*
-TEST_F(MCJITTest, multiple_empty_modules) {
- SKIP_UNSUPPORTED_PLATFORM;
-
- createJIT(M.take());
- // JIT-compile
- EXPECT_NE(0, TheJIT->getObjectImage())
- << "Unable to generate executable loaded object image";
-
- TheJIT->addModule(createEmptyModule("<other module>"));
- TheJIT->addModule(createEmptyModule("<other other module>"));
-
- // JIT again
- EXPECT_NE(0, TheJIT->getObjectImage())
- << "Unable to generate executable loaded object image";
-}
-*/
-
-// FIXME: MCJIT must support multiple modules
-/*
-TEST_F(MCJITTest, multiple_modules) {
- SKIP_UNSUPPORTED_PLATFORM;
-
- Function *Callee = insertAddFunction(M.get());
- createJIT(M.take());
-
- // caller function is defined in a different module
- M.reset(createEmptyModule("<caller module>"));
-
- Function *CalleeRef = insertExternalReferenceToFunction(M.get(), Callee);
- Function *Caller = insertSimpleCallFunction(M.get(), CalleeRef);
-
- TheJIT->addModule(M.take());
-
- // get a function pointer in a module that was not used in EE construction
- void *vPtr = TheJIT->getPointerToFunction(Caller);
- TheJIT->finalizeObject();
- EXPECT_NE(0, vPtr)
- << "Unable to get pointer to caller function from JIT";
-
- int(*FuncPtr)(int, int) = (int(*)(int, int))(intptr_t)vPtr;
- EXPECT_EQ(0, FuncPtr(0, 0));
- EXPECT_EQ(30, FuncPtr(10, 20));
- EXPECT_EQ(-30, FuncPtr(-10, -20));
-
- // ensure caller is destroyed before callee (free use before def)
- M.reset();
-}
-*/
-
}
diff --git a/unittests/ExecutionEngine/MCJIT/MCJITTestBase.h b/unittests/ExecutionEngine/MCJIT/MCJITTestBase.h
index 5debb8b..b42a9c0 100644
--- a/unittests/ExecutionEngine/MCJIT/MCJITTestBase.h
+++ b/unittests/ExecutionEngine/MCJIT/MCJITTestBase.h
@@ -119,12 +119,13 @@ protected:
// Inserts an declaration to a function defined elsewhere
Function *insertExternalReferenceToFunction(Module *M, Function *Func) {
Function *Result = Function::Create(Func->getFunctionType(),
- GlobalValue::AvailableExternallyLinkage,
+ GlobalValue::ExternalLinkage,
Func->getName(), M);
return Result;
}
// Inserts a global variable of type int32
+ // FIXME: make this a template function to support any type
GlobalVariable *insertGlobalInt32(Module *M,
StringRef name,
int32_t InitialValue) {
@@ -138,11 +139,148 @@ protected:
name);
return Global;
}
+
+ // Inserts a function
+ // int32_t recursive_add(int32_t num) {
+ // if (num == 0) {
+ // return num;
+ // } else {
+ // int32_t recursive_param = num - 1;
+ // return num + Helper(recursive_param);
+ // }
+ // }
+ // NOTE: if Helper is left as the default parameter, Helper == recursive_add.
+ Function *insertAccumulateFunction(Module *M,
+ Function *Helper = 0,
+ StringRef Name = "accumulate") {
+ Function *Result = startFunction<int32_t(int32_t)>(M, Name);
+ if (Helper == 0)
+ Helper = Result;
+
+ BasicBlock *BaseCase = BasicBlock::Create(Context, "", Result);
+ BasicBlock *RecursiveCase = BasicBlock::Create(Context, "", Result);
+
+ // if (num == 0)
+ Value *Param = Result->arg_begin();
+ Value *Zero = ConstantInt::get(Context, APInt(32, 0));
+ Builder.CreateCondBr(Builder.CreateICmpEQ(Param, Zero),
+ BaseCase, RecursiveCase);
+
+ // return num;
+ Builder.SetInsertPoint(BaseCase);
+ Builder.CreateRet(Param);
+
+ // int32_t recursive_param = num - 1;
+ // return Helper(recursive_param);
+ Builder.SetInsertPoint(RecursiveCase);
+ Value *One = ConstantInt::get(Context, APInt(32, 1));
+ Value *RecursiveParam = Builder.CreateSub(Param, One);
+ Value *RecursiveReturn = Builder.CreateCall(Helper, RecursiveParam);
+ Value *Accumulator = Builder.CreateAdd(Param, RecursiveReturn);
+ Builder.CreateRet(Accumulator);
+
+ return Result;
+ }
+
+ // Populates Modules A and B:
+ // Module A { Extern FB1, Function FA which calls FB1 },
+ // Module B { Extern FA, Function FB1, Function FB2 which calls FA },
+ void createCrossModuleRecursiveCase(OwningPtr<Module> &A,
+ Function *&FA,
+ OwningPtr<Module> &B,
+ Function *&FB1,
+ Function *&FB2) {
+ // Define FB1 in B.
+ B.reset(createEmptyModule("B"));
+ FB1 = insertAccumulateFunction(B.get(), 0, "FB1");
+
+ // Declare FB1 in A (as an external).
+ A.reset(createEmptyModule("A"));
+ Function *FB1Extern = insertExternalReferenceToFunction(A.get(), FB1);
+
+ // Define FA in A (with a call to FB1).
+ FA = insertAccumulateFunction(A.get(), FB1Extern, "FA");
+
+ // Declare FA in B (as an external)
+ Function *FAExtern = insertExternalReferenceToFunction(B.get(), FA);
+
+ // Define FB2 in B (with a call to FA)
+ FB2 = insertAccumulateFunction(B.get(), FAExtern, "FB2");
+ }
+
+ // Module A { Function FA },
+ // Module B { Extern FA, Function FB which calls FA },
+ // Module C { Extern FB, Function FC which calls FB },
+ void createThreeModuleChainedCallsCase(OwningPtr<Module> &A,
+ Function *&FA,
+ OwningPtr<Module> &B,
+ Function *&FB,
+ OwningPtr<Module> &C,
+ Function *&FC) {
+ A.reset(createEmptyModule("A"));
+ FA = insertAddFunction(A.get());
+
+ B.reset(createEmptyModule("B"));
+ Function *FAExtern_in_B = insertExternalReferenceToFunction(B.get(), FA);
+ FB = insertSimpleCallFunction<int32_t(int32_t, int32_t)>(B.get(), FAExtern_in_B);
+
+ C.reset(createEmptyModule("C"));
+ Function *FBExtern_in_C = insertExternalReferenceToFunction(C.get(), FB);
+ FC = insertSimpleCallFunction<int32_t(int32_t, int32_t)>(C.get(), FBExtern_in_C);
+ }
+
+
+ // Module A { Function FA },
+ // Populates Modules A and B:
+ // Module B { Function FB }
+ void createTwoModuleCase(OwningPtr<Module> &A, Function *&FA,
+ OwningPtr<Module> &B, Function *&FB) {
+ A.reset(createEmptyModule("A"));
+ FA = insertAddFunction(A.get());
+
+ B.reset(createEmptyModule("B"));
+ FB = insertAddFunction(B.get());
+ }
+
+ // Module A { Function FA },
+ // Module B { Extern FA, Function FB which calls FA }
+ void createTwoModuleExternCase(OwningPtr<Module> &A, Function *&FA,
+ OwningPtr<Module> &B, Function *&FB) {
+ A.reset(createEmptyModule("A"));
+ FA = insertAddFunction(A.get());
+
+ B.reset(createEmptyModule("B"));
+ Function *FAExtern_in_B = insertExternalReferenceToFunction(B.get(), FA);
+ FB = insertSimpleCallFunction<int32_t(int32_t, int32_t)>(B.get(),
+ FAExtern_in_B);
+ }
+
+ // Module A { Function FA },
+ // Module B { Extern FA, Function FB which calls FA },
+ // Module C { Extern FB, Function FC which calls FA },
+ void createThreeModuleCase(OwningPtr<Module> &A,
+ Function *&FA,
+ OwningPtr<Module> &B,
+ Function *&FB,
+ OwningPtr<Module> &C,
+ Function *&FC) {
+ A.reset(createEmptyModule("A"));
+ FA = insertAddFunction(A.get());
+
+ B.reset(createEmptyModule("B"));
+ Function *FAExtern_in_B = insertExternalReferenceToFunction(B.get(), FA);
+ FB = insertSimpleCallFunction<int32_t(int32_t, int32_t)>(B.get(), FAExtern_in_B);
+
+ C.reset(createEmptyModule("C"));
+ Function *FAExtern_in_C = insertExternalReferenceToFunction(C.get(), FA);
+ FC = insertSimpleCallFunction<int32_t(int32_t, int32_t)>(C.get(), FAExtern_in_C);
+ }
};
+
class MCJITTestBase : public MCJITTestAPICommon, public TrivialModuleBuilder {
protected:
-
+
MCJITTestBase()
: TrivialModuleBuilder(HostTriple)
, OptLevel(CodeGenOpt::None)
diff --git a/unittests/ExecutionEngine/MCJIT/Makefile b/unittests/ExecutionEngine/MCJIT/Makefile
index 454f830..33b043b 100644
--- a/unittests/ExecutionEngine/MCJIT/Makefile
+++ b/unittests/ExecutionEngine/MCJIT/Makefile
@@ -9,7 +9,7 @@
LEVEL = ../../..
TESTNAME = MCJIT
-LINK_COMPONENTS := core jit mcjit native support
+LINK_COMPONENTS := core mcjit native support
include $(LEVEL)/Makefile.config
include $(LLVM_SRC_ROOT)/unittests/Makefile.unittest
diff --git a/unittests/IR/CMakeLists.txt b/unittests/IR/CMakeLists.txt
index c53043e..fd0831f 100644
--- a/unittests/IR/CMakeLists.txt
+++ b/unittests/IR/CMakeLists.txt
@@ -10,6 +10,7 @@ set(IRSources
DominatorTreeTest.cpp
IRBuilderTest.cpp
InstructionsTest.cpp
+ LegacyPassManagerTest.cpp
MDBuilderTest.cpp
MetadataTest.cpp
PassManagerTest.cpp
diff --git a/unittests/IR/IRBuilderTest.cpp b/unittests/IR/IRBuilderTest.cpp
index fecc4a4..2f390f7 100644
--- a/unittests/IR/IRBuilderTest.cpp
+++ b/unittests/IR/IRBuilderTest.cpp
@@ -25,12 +25,12 @@ namespace {
class IRBuilderTest : public testing::Test {
protected:
virtual void SetUp() {
- M.reset(new Module("MyModule", getGlobalContext()));
- FunctionType *FTy = FunctionType::get(Type::getVoidTy(getGlobalContext()),
+ M.reset(new Module("MyModule", Ctx));
+ FunctionType *FTy = FunctionType::get(Type::getVoidTy(Ctx),
/*isVarArg=*/false);
F = Function::Create(FTy, Function::ExternalLinkage, "", M.get());
- BB = BasicBlock::Create(getGlobalContext(), "", F);
- GV = new GlobalVariable(*M, Type::getFloatTy(getGlobalContext()), true,
+ BB = BasicBlock::Create(Ctx, "", F);
+ GV = new GlobalVariable(*M, Type::getFloatTy(Ctx), true,
GlobalValue::ExternalLinkage, 0);
}
@@ -39,6 +39,7 @@ protected:
M.reset();
}
+ LLVMContext Ctx;
OwningPtr<Module> M;
Function *F;
BasicBlock *BB;
@@ -78,8 +79,8 @@ TEST_F(IRBuilderTest, Lifetime) {
TEST_F(IRBuilderTest, CreateCondBr) {
IRBuilder<> Builder(BB);
- BasicBlock *TBB = BasicBlock::Create(getGlobalContext(), "", F);
- BasicBlock *FBB = BasicBlock::Create(getGlobalContext(), "", F);
+ BasicBlock *TBB = BasicBlock::Create(Ctx, "", F);
+ BasicBlock *FBB = BasicBlock::Create(Ctx, "", F);
BranchInst *BI = Builder.CreateCondBr(Builder.getTrue(), TBB, FBB);
TerminatorInst *TI = BB->getTerminator();
@@ -89,7 +90,7 @@ TEST_F(IRBuilderTest, CreateCondBr) {
EXPECT_EQ(FBB, TI->getSuccessor(1));
BI->eraseFromParent();
- MDNode *Weights = MDBuilder(getGlobalContext()).createBranchWeights(42, 13);
+ MDNode *Weights = MDBuilder(Ctx).createBranchWeights(42, 13);
BI = Builder.CreateCondBr(Builder.getTrue(), TBB, FBB, Weights);
TI = BB->getTerminator();
EXPECT_EQ(BI, TI);
@@ -109,12 +110,12 @@ TEST_F(IRBuilderTest, LandingPadName) {
TEST_F(IRBuilderTest, GetIntTy) {
IRBuilder<> Builder(BB);
IntegerType *Ty1 = Builder.getInt1Ty();
- EXPECT_EQ(Ty1, IntegerType::get(getGlobalContext(), 1));
+ EXPECT_EQ(Ty1, IntegerType::get(Ctx, 1));
DataLayout* DL = new DataLayout(M.get());
IntegerType *IntPtrTy = Builder.getIntPtrTy(DL);
unsigned IntPtrBitSize = DL->getPointerSizeInBits(0);
- EXPECT_EQ(IntPtrTy, IntegerType::get(getGlobalContext(), IntPtrBitSize));
+ EXPECT_EQ(IntPtrTy, IntegerType::get(Ctx, IntPtrBitSize));
delete DL;
}
@@ -182,4 +183,40 @@ TEST_F(IRBuilderTest, FastMathFlags) {
}
+TEST_F(IRBuilderTest, RAIIHelpersTest) {
+ IRBuilder<> Builder(BB);
+ EXPECT_FALSE(Builder.getFastMathFlags().allowReciprocal());
+ MDBuilder MDB(M->getContext());
+
+ MDNode *FPMathA = MDB.createFPMath(0.01f);
+ MDNode *FPMathB = MDB.createFPMath(0.1f);
+
+ Builder.SetDefaultFPMathTag(FPMathA);
+
+ {
+ IRBuilder<>::FastMathFlagGuard Guard(Builder);
+ FastMathFlags FMF;
+ FMF.setAllowReciprocal();
+ Builder.SetFastMathFlags(FMF);
+ Builder.SetDefaultFPMathTag(FPMathB);
+ EXPECT_TRUE(Builder.getFastMathFlags().allowReciprocal());
+ EXPECT_EQ(FPMathB, Builder.getDefaultFPMathTag());
+ }
+
+ EXPECT_FALSE(Builder.getFastMathFlags().allowReciprocal());
+ EXPECT_EQ(FPMathA, Builder.getDefaultFPMathTag());
+
+ Value *F = Builder.CreateLoad(GV);
+
+ {
+ IRBuilder<>::InsertPointGuard Guard(Builder);
+ Builder.SetInsertPoint(cast<Instruction>(F));
+ EXPECT_EQ(F, Builder.GetInsertPoint());
+ }
+
+ EXPECT_EQ(BB->end(), Builder.GetInsertPoint());
+ EXPECT_EQ(BB, Builder.GetInsertBlock());
+}
+
+
}
diff --git a/unittests/IR/InstructionsTest.cpp b/unittests/IR/InstructionsTest.cpp
index ce6c465..65f85ba 100644
--- a/unittests/IR/InstructionsTest.cpp
+++ b/unittests/IR/InstructionsTest.cpp
@@ -149,6 +149,8 @@ TEST(InstructionsTest, CastInst) {
const Constant* c8 = Constant::getNullValue(V8x8Ty);
const Constant* c64 = Constant::getNullValue(V8x64Ty);
+ const Constant *v2ptr32 = Constant::getNullValue(V2Int32PtrTy);
+
EXPECT_TRUE(CastInst::isCastable(V8x8Ty, X86MMXTy));
EXPECT_TRUE(CastInst::isCastable(X86MMXTy, V8x8Ty));
EXPECT_FALSE(CastInst::isCastable(Int64Ty, X86MMXTy));
@@ -169,6 +171,10 @@ TEST(InstructionsTest, CastInst) {
EXPECT_FALSE(CastInst::isBitCastable(V2Int32PtrTy, V2Int32PtrAS1Ty));
EXPECT_FALSE(CastInst::isBitCastable(V2Int32PtrAS1Ty, V2Int32PtrTy));
EXPECT_TRUE(CastInst::isBitCastable(V2Int32PtrAS1Ty, V2Int64PtrAS1Ty));
+ EXPECT_TRUE(CastInst::isCastable(V2Int32PtrAS1Ty, V2Int32PtrTy));
+ EXPECT_EQ(CastInst::AddrSpaceCast, CastInst::getCastOpcode(v2ptr32, true,
+ V2Int32PtrAS1Ty,
+ true));
// Test mismatched number of elements for pointers
EXPECT_FALSE(CastInst::isBitCastable(V2Int32PtrAS1Ty, V4Int64PtrAS1Ty));
@@ -371,7 +377,6 @@ TEST(InstructionsTest, isEliminableCastPair) {
0, Int32Ty, 0),
0U);
-
// Test that we don't eliminate bitcasts between different address spaces,
// or if we don't have available pointer size information.
DataLayout DL("e-p:32:32:32-p1:16:16:16-p2:64:64:64-i1:8:8-i8:8:8-i16:16:16"
@@ -384,26 +389,18 @@ TEST(InstructionsTest, isEliminableCastPair) {
IntegerType *Int16SizePtr = DL.getIntPtrType(C, 1);
IntegerType *Int64SizePtr = DL.getIntPtrType(C, 2);
- // Fail since the ptr int types are not provided
+ // Cannot simplify inttoptr, addrspacecast
EXPECT_EQ(CastInst::isEliminableCastPair(CastInst::IntToPtr,
- CastInst::BitCast,
+ CastInst::AddrSpaceCast,
Int16Ty, Int64PtrTyAS1, Int64PtrTyAS2,
- 0, 0, 0),
- 0U);
-
- // Fail since the the bitcast is between different sized address spaces
- EXPECT_EQ(CastInst::isEliminableCastPair(
- CastInst::IntToPtr,
- CastInst::BitCast,
- Int16Ty, Int64PtrTyAS1, Int64PtrTyAS2,
- 0, Int16SizePtr, Int64SizePtr),
+ 0, Int16SizePtr, Int64SizePtr),
0U);
- // Fail since the the bitcast is between different sized address spaces
- EXPECT_EQ(CastInst::isEliminableCastPair(CastInst::IntToPtr,
- CastInst::BitCast,
- Int16Ty, Int64PtrTyAS1, Int64PtrTyAS2,
- 0, Int16SizePtr, Int64SizePtr),
+ // Cannot simplify addrspacecast, ptrtoint
+ EXPECT_EQ(CastInst::isEliminableCastPair(CastInst::AddrSpaceCast,
+ CastInst::PtrToInt,
+ Int64PtrTyAS1, Int64PtrTyAS2, Int16Ty,
+ Int64SizePtr, Int16SizePtr, 0),
0U);
// Pass since the bitcast address spaces are the same
@@ -413,28 +410,6 @@ TEST(InstructionsTest, isEliminableCastPair) {
0, 0, 0),
CastInst::IntToPtr);
-
- // Fail without known pointer sizes and different address spaces
- EXPECT_EQ(CastInst::isEliminableCastPair(CastInst::BitCast,
- CastInst::PtrToInt,
- Int64PtrTyAS1, Int64PtrTyAS2, Int16Ty,
- 0, 0, 0),
- 0U);
-
- // Pass since the address spaces are the same, even though the pointer sizes
- // are unknown
- EXPECT_EQ(CastInst::isEliminableCastPair(CastInst::BitCast,
- CastInst::PtrToInt,
- Int64PtrTyAS1, Int64PtrTyAS1, Int32Ty,
- 0, 0, 0),
- Instruction::PtrToInt);
-
- // Fail since the bitcast is the wrong size
- EXPECT_EQ(CastInst::isEliminableCastPair(CastInst::BitCast,
- CastInst::PtrToInt,
- Int64PtrTyAS1, Int64PtrTyAS2, Int64Ty,
- Int16SizePtr, Int64SizePtr, 0),
- 0U);
}
} // end anonymous namespace
diff --git a/unittests/IR/LegacyPassManagerTest.cpp b/unittests/IR/LegacyPassManagerTest.cpp
new file mode 100644
index 0000000..11841bd
--- /dev/null
+++ b/unittests/IR/LegacyPassManagerTest.cpp
@@ -0,0 +1,559 @@
+//===- llvm/unittest/IR/LegacyPassManager.cpp - Legacy PassManager tests --===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// This unit test exercises the legacy pass manager infrastructure. We use the
+// old names as well to ensure that the source-level compatibility wrapper
+// works for out-of-tree code that expects to include llvm/PassManager.h and
+// subclass the core pass classes.
+//
+//===----------------------------------------------------------------------===//
+
+#include "llvm/PassManager.h"
+#include "llvm/ADT/SmallVector.h"
+#include "llvm/Analysis/CallGraphSCCPass.h"
+#include "llvm/Analysis/LoopInfo.h"
+#include "llvm/Analysis/LoopPass.h"
+#include "llvm/Analysis/Verifier.h"
+#include "llvm/Assembly/PrintModulePass.h"
+#include "llvm/IR/BasicBlock.h"
+#include "llvm/IR/CallingConv.h"
+#include "llvm/IR/Constants.h"
+#include "llvm/IR/DataLayout.h"
+#include "llvm/IR/DerivedTypes.h"
+#include "llvm/IR/Function.h"
+#include "llvm/IR/GlobalVariable.h"
+#include "llvm/IR/InlineAsm.h"
+#include "llvm/IR/Instructions.h"
+#include "llvm/IR/LLVMContext.h"
+#include "llvm/IR/Module.h"
+#include "llvm/Pass.h"
+#include "llvm/Support/MathExtras.h"
+#include "llvm/Support/raw_ostream.h"
+#include "gtest/gtest.h"
+
+using namespace llvm;
+
+namespace llvm {
+ void initializeModuleNDMPass(PassRegistry&);
+ void initializeFPassPass(PassRegistry&);
+ void initializeCGPassPass(PassRegistry&);
+ void initializeLPassPass(PassRegistry&);
+ void initializeBPassPass(PassRegistry&);
+
+ namespace {
+ // ND = no deps
+ // NM = no modifications
+ struct ModuleNDNM: public ModulePass {
+ public:
+ static char run;
+ static char ID;
+ ModuleNDNM() : ModulePass(ID) { }
+ virtual bool runOnModule(Module &M) {
+ run++;
+ return false;
+ }
+ virtual void getAnalysisUsage(AnalysisUsage &AU) const {
+ AU.setPreservesAll();
+ }
+ };
+ char ModuleNDNM::ID=0;
+ char ModuleNDNM::run=0;
+
+ struct ModuleNDM : public ModulePass {
+ public:
+ static char run;
+ static char ID;
+ ModuleNDM() : ModulePass(ID) {}
+ virtual bool runOnModule(Module &M) {
+ run++;
+ return true;
+ }
+ };
+ char ModuleNDM::ID=0;
+ char ModuleNDM::run=0;
+
+ struct ModuleNDM2 : public ModulePass {
+ public:
+ static char run;
+ static char ID;
+ ModuleNDM2() : ModulePass(ID) {}
+ virtual bool runOnModule(Module &M) {
+ run++;
+ return true;
+ }
+ };
+ char ModuleNDM2::ID=0;
+ char ModuleNDM2::run=0;
+
+ struct ModuleDNM : public ModulePass {
+ public:
+ static char run;
+ static char ID;
+ ModuleDNM() : ModulePass(ID) {
+ initializeModuleNDMPass(*PassRegistry::getPassRegistry());
+ }
+ virtual bool runOnModule(Module &M) {
+ EXPECT_TRUE(getAnalysisIfAvailable<DataLayout>());
+ run++;
+ return false;
+ }
+ virtual void getAnalysisUsage(AnalysisUsage &AU) const {
+ AU.addRequired<ModuleNDM>();
+ AU.setPreservesAll();
+ }
+ };
+ char ModuleDNM::ID=0;
+ char ModuleDNM::run=0;
+
+ template<typename P>
+ struct PassTestBase : public P {
+ protected:
+ static int runc;
+ static bool initialized;
+ static bool finalized;
+ int allocated;
+ void run() {
+ EXPECT_TRUE(initialized);
+ EXPECT_FALSE(finalized);
+ EXPECT_EQ(0, allocated);
+ allocated++;
+ runc++;
+ }
+ public:
+ static char ID;
+ static void finishedOK(int run) {
+ EXPECT_GT(runc, 0);
+ EXPECT_TRUE(initialized);
+ EXPECT_TRUE(finalized);
+ EXPECT_EQ(run, runc);
+ }
+ PassTestBase() : P(ID), allocated(0) {
+ initialized = false;
+ finalized = false;
+ runc = 0;
+ }
+
+ virtual void releaseMemory() {
+ EXPECT_GT(runc, 0);
+ EXPECT_GT(allocated, 0);
+ allocated--;
+ }
+ };
+ template<typename P> char PassTestBase<P>::ID;
+ template<typename P> int PassTestBase<P>::runc;
+ template<typename P> bool PassTestBase<P>::initialized;
+ template<typename P> bool PassTestBase<P>::finalized;
+
+ template<typename T, typename P>
+ struct PassTest : public PassTestBase<P> {
+ public:
+#ifndef _MSC_VER // MSVC complains that Pass is not base class.
+ using llvm::Pass::doInitialization;
+ using llvm::Pass::doFinalization;
+#endif
+ virtual bool doInitialization(T &t) {
+ EXPECT_FALSE(PassTestBase<P>::initialized);
+ PassTestBase<P>::initialized = true;
+ return false;
+ }
+ virtual bool doFinalization(T &t) {
+ EXPECT_FALSE(PassTestBase<P>::finalized);
+ PassTestBase<P>::finalized = true;
+ EXPECT_EQ(0, PassTestBase<P>::allocated);
+ return false;
+ }
+ };
+
+ struct CGPass : public PassTest<CallGraph, CallGraphSCCPass> {
+ public:
+ CGPass() {
+ initializeCGPassPass(*PassRegistry::getPassRegistry());
+ }
+ virtual bool runOnSCC(CallGraphSCC &SCMM) {
+ EXPECT_TRUE(getAnalysisIfAvailable<DataLayout>());
+ run();
+ return false;
+ }
+ };
+
+ struct FPass : public PassTest<Module, FunctionPass> {
+ public:
+ virtual bool runOnFunction(Function &F) {
+ // FIXME: PR4112
+ // EXPECT_TRUE(getAnalysisIfAvailable<DataLayout>());
+ run();
+ return false;
+ }
+ };
+
+ struct LPass : public PassTestBase<LoopPass> {
+ private:
+ static int initcount;
+ static int fincount;
+ public:
+ LPass() {
+ initializeLPassPass(*PassRegistry::getPassRegistry());
+ initcount = 0; fincount=0;
+ EXPECT_FALSE(initialized);
+ }
+ static void finishedOK(int run, int finalized) {
+ PassTestBase<LoopPass>::finishedOK(run);
+ EXPECT_EQ(run, initcount);
+ EXPECT_EQ(finalized, fincount);
+ }
+ using llvm::Pass::doInitialization;
+ using llvm::Pass::doFinalization;
+ virtual bool doInitialization(Loop* L, LPPassManager &LPM) {
+ initialized = true;
+ initcount++;
+ return false;
+ }
+ virtual bool runOnLoop(Loop *L, LPPassManager &LPM) {
+ EXPECT_TRUE(getAnalysisIfAvailable<DataLayout>());
+ run();
+ return false;
+ }
+ virtual bool doFinalization() {
+ fincount++;
+ finalized = true;
+ return false;
+ }
+ };
+ int LPass::initcount=0;
+ int LPass::fincount=0;
+
+ struct BPass : public PassTestBase<BasicBlockPass> {
+ private:
+ static int inited;
+ static int fin;
+ public:
+ static void finishedOK(int run, int N) {
+ PassTestBase<BasicBlockPass>::finishedOK(run);
+ EXPECT_EQ(inited, N);
+ EXPECT_EQ(fin, N);
+ }
+ BPass() {
+ inited = 0;
+ fin = 0;
+ }
+ virtual bool doInitialization(Module &M) {
+ EXPECT_FALSE(initialized);
+ initialized = true;
+ return false;
+ }
+ virtual bool doInitialization(Function &F) {
+ inited++;
+ return false;
+ }
+ virtual bool runOnBasicBlock(BasicBlock &BB) {
+ EXPECT_TRUE(getAnalysisIfAvailable<DataLayout>());
+ run();
+ return false;
+ }
+ virtual bool doFinalization(Function &F) {
+ fin++;
+ return false;
+ }
+ virtual bool doFinalization(Module &M) {
+ EXPECT_FALSE(finalized);
+ finalized = true;
+ EXPECT_EQ(0, allocated);
+ return false;
+ }
+ };
+ int BPass::inited=0;
+ int BPass::fin=0;
+
+ struct OnTheFlyTest: public ModulePass {
+ public:
+ static char ID;
+ OnTheFlyTest() : ModulePass(ID) {
+ initializeFPassPass(*PassRegistry::getPassRegistry());
+ }
+ virtual bool runOnModule(Module &M) {
+ EXPECT_TRUE(getAnalysisIfAvailable<DataLayout>());
+ for (Module::iterator I=M.begin(),E=M.end(); I != E; ++I) {
+ Function &F = *I;
+ {
+ SCOPED_TRACE("Running on the fly function pass");
+ getAnalysis<FPass>(F);
+ }
+ }
+ return false;
+ }
+ virtual void getAnalysisUsage(AnalysisUsage &AU) const {
+ AU.addRequired<FPass>();
+ }
+ };
+ char OnTheFlyTest::ID=0;
+
+ TEST(PassManager, RunOnce) {
+ Module M("test-once", getGlobalContext());
+ struct ModuleNDNM *mNDNM = new ModuleNDNM();
+ struct ModuleDNM *mDNM = new ModuleDNM();
+ struct ModuleNDM *mNDM = new ModuleNDM();
+ struct ModuleNDM2 *mNDM2 = new ModuleNDM2();
+
+ mNDM->run = mNDNM->run = mDNM->run = mNDM2->run = 0;
+
+ PassManager Passes;
+ Passes.add(new DataLayout(&M));
+ Passes.add(mNDM2);
+ Passes.add(mNDM);
+ Passes.add(mNDNM);
+ Passes.add(mDNM);
+
+ Passes.run(M);
+ // each pass must be run exactly once, since nothing invalidates them
+ EXPECT_EQ(1, mNDM->run);
+ EXPECT_EQ(1, mNDNM->run);
+ EXPECT_EQ(1, mDNM->run);
+ EXPECT_EQ(1, mNDM2->run);
+ }
+
+ TEST(PassManager, ReRun) {
+ Module M("test-rerun", getGlobalContext());
+ struct ModuleNDNM *mNDNM = new ModuleNDNM();
+ struct ModuleDNM *mDNM = new ModuleDNM();
+ struct ModuleNDM *mNDM = new ModuleNDM();
+ struct ModuleNDM2 *mNDM2 = new ModuleNDM2();
+
+ mNDM->run = mNDNM->run = mDNM->run = mNDM2->run = 0;
+
+ PassManager Passes;
+ Passes.add(new DataLayout(&M));
+ Passes.add(mNDM);
+ Passes.add(mNDNM);
+ Passes.add(mNDM2);// invalidates mNDM needed by mDNM
+ Passes.add(mDNM);
+
+ Passes.run(M);
+ // Some passes must be rerun because a pass that modified the
+ // module/function was run in between
+ EXPECT_EQ(2, mNDM->run);
+ EXPECT_EQ(1, mNDNM->run);
+ EXPECT_EQ(1, mNDM2->run);
+ EXPECT_EQ(1, mDNM->run);
+ }
+
+ Module* makeLLVMModule();
+
+ template<typename T>
+ void MemoryTestHelper(int run) {
+ OwningPtr<Module> M(makeLLVMModule());
+ T *P = new T();
+ PassManager Passes;
+ Passes.add(new DataLayout(M.get()));
+ Passes.add(P);
+ Passes.run(*M);
+ T::finishedOK(run);
+ }
+
+ template<typename T>
+ void MemoryTestHelper(int run, int N) {
+ Module *M = makeLLVMModule();
+ T *P = new T();
+ PassManager Passes;
+ Passes.add(new DataLayout(M));
+ Passes.add(P);
+ Passes.run(*M);
+ T::finishedOK(run, N);
+ delete M;
+ }
+
+ TEST(PassManager, Memory) {
+ // SCC#1: test1->test2->test3->test1
+ // SCC#2: test4
+ // SCC#3: indirect call node
+ {
+ SCOPED_TRACE("Callgraph pass");
+ MemoryTestHelper<CGPass>(3);
+ }
+
+ {
+ SCOPED_TRACE("Function pass");
+ MemoryTestHelper<FPass>(4);// 4 functions
+ }
+
+ {
+ SCOPED_TRACE("Loop pass");
+ MemoryTestHelper<LPass>(2, 1); //2 loops, 1 function
+ }
+ {
+ SCOPED_TRACE("Basic block pass");
+ MemoryTestHelper<BPass>(7, 4); //9 basic blocks
+ }
+
+ }
+
+ TEST(PassManager, MemoryOnTheFly) {
+ Module *M = makeLLVMModule();
+ {
+ SCOPED_TRACE("Running OnTheFlyTest");
+ struct OnTheFlyTest *O = new OnTheFlyTest();
+ PassManager Passes;
+ Passes.add(new DataLayout(M));
+ Passes.add(O);
+ Passes.run(*M);
+
+ FPass::finishedOK(4);
+ }
+ delete M;
+ }
+
+ Module* makeLLVMModule() {
+ // Module Construction
+ Module* mod = new Module("test-mem", getGlobalContext());
+ mod->setDataLayout("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");
+ mod->setTargetTriple("x86_64-unknown-linux-gnu");
+
+ // Type Definitions
+ std::vector<Type*>FuncTy_0_args;
+ FunctionType* FuncTy_0 = FunctionType::get(
+ /*Result=*/IntegerType::get(getGlobalContext(), 32),
+ /*Params=*/FuncTy_0_args,
+ /*isVarArg=*/false);
+
+ std::vector<Type*>FuncTy_2_args;
+ FuncTy_2_args.push_back(IntegerType::get(getGlobalContext(), 1));
+ FunctionType* FuncTy_2 = FunctionType::get(
+ /*Result=*/Type::getVoidTy(getGlobalContext()),
+ /*Params=*/FuncTy_2_args,
+ /*isVarArg=*/false);
+
+
+ // Function Declarations
+
+ Function* func_test1 = Function::Create(
+ /*Type=*/FuncTy_0,
+ /*Linkage=*/GlobalValue::ExternalLinkage,
+ /*Name=*/"test1", mod);
+ func_test1->setCallingConv(CallingConv::C);
+ AttributeSet func_test1_PAL;
+ func_test1->setAttributes(func_test1_PAL);
+
+ Function* func_test2 = Function::Create(
+ /*Type=*/FuncTy_0,
+ /*Linkage=*/GlobalValue::ExternalLinkage,
+ /*Name=*/"test2", mod);
+ func_test2->setCallingConv(CallingConv::C);
+ AttributeSet func_test2_PAL;
+ func_test2->setAttributes(func_test2_PAL);
+
+ Function* func_test3 = Function::Create(
+ /*Type=*/FuncTy_0,
+ /*Linkage=*/GlobalValue::ExternalLinkage,
+ /*Name=*/"test3", mod);
+ func_test3->setCallingConv(CallingConv::C);
+ AttributeSet func_test3_PAL;
+ func_test3->setAttributes(func_test3_PAL);
+
+ Function* func_test4 = Function::Create(
+ /*Type=*/FuncTy_2,
+ /*Linkage=*/GlobalValue::ExternalLinkage,
+ /*Name=*/"test4", mod);
+ func_test4->setCallingConv(CallingConv::C);
+ AttributeSet func_test4_PAL;
+ func_test4->setAttributes(func_test4_PAL);
+
+ // Global Variable Declarations
+
+
+ // Constant Definitions
+
+ // Global Variable Definitions
+
+ // Function Definitions
+
+ // Function: test1 (func_test1)
+ {
+
+ BasicBlock* label_entry = BasicBlock::Create(getGlobalContext(), "entry",func_test1,0);
+
+ // Block entry (label_entry)
+ CallInst* int32_3 = CallInst::Create(func_test2, "", label_entry);
+ int32_3->setCallingConv(CallingConv::C);
+ int32_3->setTailCall(false);AttributeSet int32_3_PAL;
+ int32_3->setAttributes(int32_3_PAL);
+
+ ReturnInst::Create(getGlobalContext(), int32_3, label_entry);
+
+ }
+
+ // Function: test2 (func_test2)
+ {
+
+ BasicBlock* label_entry_5 = BasicBlock::Create(getGlobalContext(), "entry",func_test2,0);
+
+ // Block entry (label_entry_5)
+ CallInst* int32_6 = CallInst::Create(func_test3, "", label_entry_5);
+ int32_6->setCallingConv(CallingConv::C);
+ int32_6->setTailCall(false);AttributeSet int32_6_PAL;
+ int32_6->setAttributes(int32_6_PAL);
+
+ ReturnInst::Create(getGlobalContext(), int32_6, label_entry_5);
+
+ }
+
+ // Function: test3 (func_test3)
+ {
+
+ BasicBlock* label_entry_8 = BasicBlock::Create(getGlobalContext(), "entry",func_test3,0);
+
+ // Block entry (label_entry_8)
+ CallInst* int32_9 = CallInst::Create(func_test1, "", label_entry_8);
+ int32_9->setCallingConv(CallingConv::C);
+ int32_9->setTailCall(false);AttributeSet int32_9_PAL;
+ int32_9->setAttributes(int32_9_PAL);
+
+ ReturnInst::Create(getGlobalContext(), int32_9, label_entry_8);
+
+ }
+
+ // Function: test4 (func_test4)
+ {
+ Function::arg_iterator args = func_test4->arg_begin();
+ Value* int1_f = args++;
+ int1_f->setName("f");
+
+ BasicBlock* label_entry_11 = BasicBlock::Create(getGlobalContext(), "entry",func_test4,0);
+ BasicBlock* label_bb = BasicBlock::Create(getGlobalContext(), "bb",func_test4,0);
+ BasicBlock* label_bb1 = BasicBlock::Create(getGlobalContext(), "bb1",func_test4,0);
+ BasicBlock* label_return = BasicBlock::Create(getGlobalContext(), "return",func_test4,0);
+
+ // Block entry (label_entry_11)
+ BranchInst::Create(label_bb, label_entry_11);
+
+ // Block bb (label_bb)
+ BranchInst::Create(label_bb, label_bb1, int1_f, label_bb);
+
+ // Block bb1 (label_bb1)
+ BranchInst::Create(label_bb1, label_return, int1_f, label_bb1);
+
+ // Block return (label_return)
+ ReturnInst::Create(getGlobalContext(), label_return);
+
+ }
+ return mod;
+ }
+
+ }
+}
+
+INITIALIZE_PASS(ModuleNDM, "mndm", "mndm", false, false)
+INITIALIZE_PASS_BEGIN(CGPass, "cgp","cgp", false, false)
+INITIALIZE_PASS_DEPENDENCY(CallGraph)
+INITIALIZE_PASS_END(CGPass, "cgp","cgp", false, false)
+INITIALIZE_PASS(FPass, "fp","fp", false, false)
+INITIALIZE_PASS_BEGIN(LPass, "lp","lp", false, false)
+INITIALIZE_PASS_DEPENDENCY(LoopInfo)
+INITIALIZE_PASS_END(LPass, "lp","lp", false, false)
+INITIALIZE_PASS(BPass, "bp","bp", false, false)
diff --git a/unittests/IR/PassManagerTest.cpp b/unittests/IR/PassManagerTest.cpp
index 1097da6..7b60e38 100644
--- a/unittests/IR/PassManagerTest.cpp
+++ b/unittests/IR/PassManagerTest.cpp
@@ -1,4 +1,4 @@
-//===- llvm/unittest/IR/PassManager.cpp - PassManager unit tests ----------===//
+//===- llvm/unittest/IR/PassManager.cpp - PassManager tests ---------------===//
//
// The LLVM Compiler Infrastructure
//
@@ -7,546 +7,125 @@
//
//===----------------------------------------------------------------------===//
-#include "llvm/PassManager.h"
-#include "llvm/ADT/SmallVector.h"
-#include "llvm/Analysis/CallGraphSCCPass.h"
-#include "llvm/Analysis/LoopInfo.h"
-#include "llvm/Analysis/LoopPass.h"
-#include "llvm/Analysis/Verifier.h"
-#include "llvm/Assembly/PrintModulePass.h"
-#include "llvm/IR/BasicBlock.h"
-#include "llvm/IR/CallingConv.h"
-#include "llvm/IR/Constants.h"
-#include "llvm/IR/DataLayout.h"
-#include "llvm/IR/DerivedTypes.h"
+#include "llvm/Assembly/Parser.h"
#include "llvm/IR/Function.h"
-#include "llvm/IR/GlobalVariable.h"
-#include "llvm/IR/InlineAsm.h"
-#include "llvm/IR/Instructions.h"
#include "llvm/IR/LLVMContext.h"
#include "llvm/IR/Module.h"
-#include "llvm/Pass.h"
-#include "llvm/Support/MathExtras.h"
-#include "llvm/Support/raw_ostream.h"
+#include "llvm/IR/PassManager.h"
+#include "llvm/Support/SourceMgr.h"
#include "gtest/gtest.h"
using namespace llvm;
-namespace llvm {
- void initializeModuleNDMPass(PassRegistry&);
- void initializeFPassPass(PassRegistry&);
- void initializeCGPassPass(PassRegistry&);
- void initializeLPassPass(PassRegistry&);
- void initializeBPassPass(PassRegistry&);
-
- namespace {
- // ND = no deps
- // NM = no modifications
- struct ModuleNDNM: public ModulePass {
- public:
- static char run;
- static char ID;
- ModuleNDNM() : ModulePass(ID) { }
- virtual bool runOnModule(Module &M) {
- run++;
- return false;
- }
- virtual void getAnalysisUsage(AnalysisUsage &AU) const {
- AU.setPreservesAll();
- }
- };
- char ModuleNDNM::ID=0;
- char ModuleNDNM::run=0;
-
- struct ModuleNDM : public ModulePass {
- public:
- static char run;
- static char ID;
- ModuleNDM() : ModulePass(ID) {}
- virtual bool runOnModule(Module &M) {
- run++;
- return true;
- }
- };
- char ModuleNDM::ID=0;
- char ModuleNDM::run=0;
-
- struct ModuleNDM2 : public ModulePass {
- public:
- static char run;
- static char ID;
- ModuleNDM2() : ModulePass(ID) {}
- virtual bool runOnModule(Module &M) {
- run++;
- return true;
- }
- };
- char ModuleNDM2::ID=0;
- char ModuleNDM2::run=0;
-
- struct ModuleDNM : public ModulePass {
- public:
- static char run;
- static char ID;
- ModuleDNM() : ModulePass(ID) {
- initializeModuleNDMPass(*PassRegistry::getPassRegistry());
- }
- virtual bool runOnModule(Module &M) {
- EXPECT_TRUE(getAnalysisIfAvailable<DataLayout>());
- run++;
- return false;
- }
- virtual void getAnalysisUsage(AnalysisUsage &AU) const {
- AU.addRequired<ModuleNDM>();
- AU.setPreservesAll();
- }
- };
- char ModuleDNM::ID=0;
- char ModuleDNM::run=0;
-
- template<typename P>
- struct PassTestBase : public P {
- protected:
- static int runc;
- static bool initialized;
- static bool finalized;
- int allocated;
- void run() {
- EXPECT_TRUE(initialized);
- EXPECT_FALSE(finalized);
- EXPECT_EQ(0, allocated);
- allocated++;
- runc++;
- }
- public:
- static char ID;
- static void finishedOK(int run) {
- EXPECT_GT(runc, 0);
- EXPECT_TRUE(initialized);
- EXPECT_TRUE(finalized);
- EXPECT_EQ(run, runc);
- }
- PassTestBase() : P(ID), allocated(0) {
- initialized = false;
- finalized = false;
- runc = 0;
- }
-
- virtual void releaseMemory() {
- EXPECT_GT(runc, 0);
- EXPECT_GT(allocated, 0);
- allocated--;
- }
- };
- template<typename P> char PassTestBase<P>::ID;
- template<typename P> int PassTestBase<P>::runc;
- template<typename P> bool PassTestBase<P>::initialized;
- template<typename P> bool PassTestBase<P>::finalized;
-
- template<typename T, typename P>
- struct PassTest : public PassTestBase<P> {
- public:
-#ifndef _MSC_VER // MSVC complains that Pass is not base class.
- using llvm::Pass::doInitialization;
- using llvm::Pass::doFinalization;
-#endif
- virtual bool doInitialization(T &t) {
- EXPECT_FALSE(PassTestBase<P>::initialized);
- PassTestBase<P>::initialized = true;
- return false;
- }
- virtual bool doFinalization(T &t) {
- EXPECT_FALSE(PassTestBase<P>::finalized);
- PassTestBase<P>::finalized = true;
- EXPECT_EQ(0, PassTestBase<P>::allocated);
- return false;
- }
- };
-
- struct CGPass : public PassTest<CallGraph, CallGraphSCCPass> {
- public:
- CGPass() {
- initializeCGPassPass(*PassRegistry::getPassRegistry());
- }
- virtual bool runOnSCC(CallGraphSCC &SCMM) {
- EXPECT_TRUE(getAnalysisIfAvailable<DataLayout>());
- run();
- return false;
- }
- };
-
- struct FPass : public PassTest<Module, FunctionPass> {
- public:
- virtual bool runOnFunction(Function &F) {
- // FIXME: PR4112
- // EXPECT_TRUE(getAnalysisIfAvailable<DataLayout>());
- run();
- return false;
- }
- };
-
- struct LPass : public PassTestBase<LoopPass> {
- private:
- static int initcount;
- static int fincount;
- public:
- LPass() {
- initializeLPassPass(*PassRegistry::getPassRegistry());
- initcount = 0; fincount=0;
- EXPECT_FALSE(initialized);
- }
- static void finishedOK(int run, int finalized) {
- PassTestBase<LoopPass>::finishedOK(run);
- EXPECT_EQ(run, initcount);
- EXPECT_EQ(finalized, fincount);
- }
- using llvm::Pass::doInitialization;
- using llvm::Pass::doFinalization;
- virtual bool doInitialization(Loop* L, LPPassManager &LPM) {
- initialized = true;
- initcount++;
- return false;
- }
- virtual bool runOnLoop(Loop *L, LPPassManager &LPM) {
- EXPECT_TRUE(getAnalysisIfAvailable<DataLayout>());
- run();
- return false;
- }
- virtual bool doFinalization() {
- fincount++;
- finalized = true;
- return false;
- }
- };
- int LPass::initcount=0;
- int LPass::fincount=0;
-
- struct BPass : public PassTestBase<BasicBlockPass> {
- private:
- static int inited;
- static int fin;
- public:
- static void finishedOK(int run, int N) {
- PassTestBase<BasicBlockPass>::finishedOK(run);
- EXPECT_EQ(inited, N);
- EXPECT_EQ(fin, N);
- }
- BPass() {
- inited = 0;
- fin = 0;
- }
- virtual bool doInitialization(Module &M) {
- EXPECT_FALSE(initialized);
- initialized = true;
- return false;
- }
- virtual bool doInitialization(Function &F) {
- inited++;
- return false;
- }
- virtual bool runOnBasicBlock(BasicBlock &BB) {
- EXPECT_TRUE(getAnalysisIfAvailable<DataLayout>());
- run();
- return false;
- }
- virtual bool doFinalization(Function &F) {
- fin++;
- return false;
- }
- virtual bool doFinalization(Module &M) {
- EXPECT_FALSE(finalized);
- finalized = true;
- EXPECT_EQ(0, allocated);
- return false;
- }
- };
- int BPass::inited=0;
- int BPass::fin=0;
-
- struct OnTheFlyTest: public ModulePass {
- public:
- static char ID;
- OnTheFlyTest() : ModulePass(ID) {
- initializeFPassPass(*PassRegistry::getPassRegistry());
- }
- virtual bool runOnModule(Module &M) {
- EXPECT_TRUE(getAnalysisIfAvailable<DataLayout>());
- for (Module::iterator I=M.begin(),E=M.end(); I != E; ++I) {
- Function &F = *I;
- {
- SCOPED_TRACE("Running on the fly function pass");
- getAnalysis<FPass>(F);
- }
- }
- return false;
- }
- virtual void getAnalysisUsage(AnalysisUsage &AU) const {
- AU.addRequired<FPass>();
- }
- };
- char OnTheFlyTest::ID=0;
-
- TEST(PassManager, RunOnce) {
- Module M("test-once", getGlobalContext());
- struct ModuleNDNM *mNDNM = new ModuleNDNM();
- struct ModuleDNM *mDNM = new ModuleDNM();
- struct ModuleNDM *mNDM = new ModuleNDM();
- struct ModuleNDM2 *mNDM2 = new ModuleNDM2();
-
- mNDM->run = mNDNM->run = mDNM->run = mNDM2->run = 0;
-
- PassManager Passes;
- Passes.add(new DataLayout(&M));
- Passes.add(mNDM2);
- Passes.add(mNDM);
- Passes.add(mNDNM);
- Passes.add(mDNM);
-
- Passes.run(M);
- // each pass must be run exactly once, since nothing invalidates them
- EXPECT_EQ(1, mNDM->run);
- EXPECT_EQ(1, mNDNM->run);
- EXPECT_EQ(1, mDNM->run);
- EXPECT_EQ(1, mNDM2->run);
- }
-
- TEST(PassManager, ReRun) {
- Module M("test-rerun", getGlobalContext());
- struct ModuleNDNM *mNDNM = new ModuleNDNM();
- struct ModuleDNM *mDNM = new ModuleDNM();
- struct ModuleNDM *mNDM = new ModuleNDM();
- struct ModuleNDM2 *mNDM2 = new ModuleNDM2();
-
- mNDM->run = mNDNM->run = mDNM->run = mNDM2->run = 0;
-
- PassManager Passes;
- Passes.add(new DataLayout(&M));
- Passes.add(mNDM);
- Passes.add(mNDNM);
- Passes.add(mNDM2);// invalidates mNDM needed by mDNM
- Passes.add(mDNM);
-
- Passes.run(M);
- // Some passes must be rerun because a pass that modified the
- // module/function was run in between
- EXPECT_EQ(2, mNDM->run);
- EXPECT_EQ(1, mNDNM->run);
- EXPECT_EQ(1, mNDM2->run);
- EXPECT_EQ(1, mDNM->run);
- }
-
- Module* makeLLVMModule();
-
- template<typename T>
- void MemoryTestHelper(int run) {
- OwningPtr<Module> M(makeLLVMModule());
- T *P = new T();
- PassManager Passes;
- Passes.add(new DataLayout(M.get()));
- Passes.add(P);
- Passes.run(*M);
- T::finishedOK(run);
- }
-
- template<typename T>
- void MemoryTestHelper(int run, int N) {
- Module *M = makeLLVMModule();
- T *P = new T();
- PassManager Passes;
- Passes.add(new DataLayout(M));
- Passes.add(P);
- Passes.run(*M);
- T::finishedOK(run, N);
- delete M;
- }
-
- TEST(PassManager, Memory) {
- // SCC#1: test1->test2->test3->test1
- // SCC#2: test4
- // SCC#3: indirect call node
- {
- SCOPED_TRACE("Callgraph pass");
- MemoryTestHelper<CGPass>(3);
- }
-
- {
- SCOPED_TRACE("Function pass");
- MemoryTestHelper<FPass>(4);// 4 functions
- }
-
- {
- SCOPED_TRACE("Loop pass");
- MemoryTestHelper<LPass>(2, 1); //2 loops, 1 function
- }
- {
- SCOPED_TRACE("Basic block pass");
- MemoryTestHelper<BPass>(7, 4); //9 basic blocks
- }
-
- }
-
- TEST(PassManager, MemoryOnTheFly) {
- Module *M = makeLLVMModule();
- {
- SCOPED_TRACE("Running OnTheFlyTest");
- struct OnTheFlyTest *O = new OnTheFlyTest();
- PassManager Passes;
- Passes.add(new DataLayout(M));
- Passes.add(O);
- Passes.run(*M);
-
- FPass::finishedOK(4);
- }
- delete M;
- }
-
- Module* makeLLVMModule() {
- // Module Construction
- Module* mod = new Module("test-mem", getGlobalContext());
- mod->setDataLayout("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");
- mod->setTargetTriple("x86_64-unknown-linux-gnu");
-
- // Type Definitions
- std::vector<Type*>FuncTy_0_args;
- FunctionType* FuncTy_0 = FunctionType::get(
- /*Result=*/IntegerType::get(getGlobalContext(), 32),
- /*Params=*/FuncTy_0_args,
- /*isVarArg=*/false);
-
- std::vector<Type*>FuncTy_2_args;
- FuncTy_2_args.push_back(IntegerType::get(getGlobalContext(), 1));
- FunctionType* FuncTy_2 = FunctionType::get(
- /*Result=*/Type::getVoidTy(getGlobalContext()),
- /*Params=*/FuncTy_2_args,
- /*isVarArg=*/false);
-
-
- // Function Declarations
-
- Function* func_test1 = Function::Create(
- /*Type=*/FuncTy_0,
- /*Linkage=*/GlobalValue::ExternalLinkage,
- /*Name=*/"test1", mod);
- func_test1->setCallingConv(CallingConv::C);
- AttributeSet func_test1_PAL;
- func_test1->setAttributes(func_test1_PAL);
-
- Function* func_test2 = Function::Create(
- /*Type=*/FuncTy_0,
- /*Linkage=*/GlobalValue::ExternalLinkage,
- /*Name=*/"test2", mod);
- func_test2->setCallingConv(CallingConv::C);
- AttributeSet func_test2_PAL;
- func_test2->setAttributes(func_test2_PAL);
-
- Function* func_test3 = Function::Create(
- /*Type=*/FuncTy_0,
- /*Linkage=*/GlobalValue::ExternalLinkage,
- /*Name=*/"test3", mod);
- func_test3->setCallingConv(CallingConv::C);
- AttributeSet func_test3_PAL;
- func_test3->setAttributes(func_test3_PAL);
-
- Function* func_test4 = Function::Create(
- /*Type=*/FuncTy_2,
- /*Linkage=*/GlobalValue::ExternalLinkage,
- /*Name=*/"test4", mod);
- func_test4->setCallingConv(CallingConv::C);
- AttributeSet func_test4_PAL;
- func_test4->setAttributes(func_test4_PAL);
-
- // Global Variable Declarations
-
-
- // Constant Definitions
-
- // Global Variable Definitions
-
- // Function Definitions
-
- // Function: test1 (func_test1)
- {
-
- BasicBlock* label_entry = BasicBlock::Create(getGlobalContext(), "entry",func_test1,0);
-
- // Block entry (label_entry)
- CallInst* int32_3 = CallInst::Create(func_test2, "", label_entry);
- int32_3->setCallingConv(CallingConv::C);
- int32_3->setTailCall(false);AttributeSet int32_3_PAL;
- int32_3->setAttributes(int32_3_PAL);
-
- ReturnInst::Create(getGlobalContext(), int32_3, label_entry);
-
- }
-
- // Function: test2 (func_test2)
- {
-
- BasicBlock* label_entry_5 = BasicBlock::Create(getGlobalContext(), "entry",func_test2,0);
-
- // Block entry (label_entry_5)
- CallInst* int32_6 = CallInst::Create(func_test3, "", label_entry_5);
- int32_6->setCallingConv(CallingConv::C);
- int32_6->setTailCall(false);AttributeSet int32_6_PAL;
- int32_6->setAttributes(int32_6_PAL);
-
- ReturnInst::Create(getGlobalContext(), int32_6, label_entry_5);
-
- }
-
- // Function: test3 (func_test3)
- {
+namespace {
+
+class TestAnalysisPass {
+public:
+ typedef Function IRUnitT;
+
+ struct Result {
+ Result(int Count) : InstructionCount(Count) {}
+ bool invalidate(Function *) { return true; }
+ int InstructionCount;
+ };
+
+ /// \brief Returns an opaque, unique ID for this pass type.
+ static void *ID() { return (void *)&PassID; }
+
+ /// \brief Run the analysis pass over the function and return a result.
+ Result run(Function *F) {
+ int Count = 0;
+ for (Function::iterator BBI = F->begin(), BBE = F->end(); BBI != BBE; ++BBI)
+ for (BasicBlock::iterator II = BBI->begin(), IE = BBI->end(); II != IE;
+ ++II)
+ ++Count;
+ return Result(Count);
+ }
- BasicBlock* label_entry_8 = BasicBlock::Create(getGlobalContext(), "entry",func_test3,0);
+private:
+ /// \brief Private static data to provide unique ID.
+ static char PassID;
+};
- // Block entry (label_entry_8)
- CallInst* int32_9 = CallInst::Create(func_test1, "", label_entry_8);
- int32_9->setCallingConv(CallingConv::C);
- int32_9->setTailCall(false);AttributeSet int32_9_PAL;
- int32_9->setAttributes(int32_9_PAL);
+char TestAnalysisPass::PassID;
- ReturnInst::Create(getGlobalContext(), int32_9, label_entry_8);
+struct TestModulePass {
+ TestModulePass(int &RunCount) : RunCount(RunCount) {}
- }
+ bool run(Module *M) {
+ ++RunCount;
+ return true;
+ }
- // Function: test4 (func_test4)
- {
- Function::arg_iterator args = func_test4->arg_begin();
- Value* int1_f = args++;
- int1_f->setName("f");
+ int &RunCount;
+};
- BasicBlock* label_entry_11 = BasicBlock::Create(getGlobalContext(), "entry",func_test4,0);
- BasicBlock* label_bb = BasicBlock::Create(getGlobalContext(), "bb",func_test4,0);
- BasicBlock* label_bb1 = BasicBlock::Create(getGlobalContext(), "bb1",func_test4,0);
- BasicBlock* label_return = BasicBlock::Create(getGlobalContext(), "return",func_test4,0);
+struct TestFunctionPass {
+ TestFunctionPass(AnalysisManager &AM, int &RunCount, int &AnalyzedInstrCount)
+ : AM(AM), RunCount(RunCount), AnalyzedInstrCount(AnalyzedInstrCount) {
+ }
- // Block entry (label_entry_11)
- BranchInst::Create(label_bb, label_entry_11);
+ bool run(Function *F) {
+ ++RunCount;
- // Block bb (label_bb)
- BranchInst::Create(label_bb, label_bb1, int1_f, label_bb);
+ const TestAnalysisPass::Result &AR = AM.getResult<TestAnalysisPass>(F);
+ AnalyzedInstrCount += AR.InstructionCount;
- // Block bb1 (label_bb1)
- BranchInst::Create(label_bb1, label_return, int1_f, label_bb1);
+ return true;
+ }
- // Block return (label_return)
- ReturnInst::Create(getGlobalContext(), label_return);
+ AnalysisManager &AM;
+ int &RunCount;
+ int &AnalyzedInstrCount;
+};
- }
- return mod;
- }
+Module *parseIR(const char *IR) {
+ LLVMContext &C = getGlobalContext();
+ SMDiagnostic Err;
+ return ParseAssemblyString(IR, 0, Err, C);
+}
- }
+class PassManagerTest : public ::testing::Test {
+protected:
+ OwningPtr<Module> M;
+
+public:
+ PassManagerTest()
+ : M(parseIR("define void @f() {\n"
+ "entry:\n"
+ " call void @g()\n"
+ " call void @h()\n"
+ " ret void\n"
+ "}\n"
+ "define void @g() {\n"
+ " ret void\n"
+ "}\n"
+ "define void @h() {\n"
+ " ret void\n"
+ "}\n")) {}
+};
+
+TEST_F(PassManagerTest, Basic) {
+ AnalysisManager AM(M.get());
+ AM.registerAnalysisPass(TestAnalysisPass());
+
+ ModulePassManager MPM(M.get(), &AM);
+ FunctionPassManager FPM(&AM);
+
+ // Count the runs over a module.
+ int ModulePassRunCount = 0;
+ MPM.addPass(TestModulePass(ModulePassRunCount));
+
+ // Count the runs over a Function.
+ int FunctionPassRunCount = 0;
+ int AnalyzedInstrCount = 0;
+ FPM.addPass(TestFunctionPass(AM, FunctionPassRunCount, AnalyzedInstrCount));
+ MPM.addPass(FPM);
+
+ MPM.run();
+ EXPECT_EQ(1, ModulePassRunCount);
+ EXPECT_EQ(3, FunctionPassRunCount);
+ EXPECT_EQ(5, AnalyzedInstrCount);
}
-INITIALIZE_PASS(ModuleNDM, "mndm", "mndm", false, false)
-INITIALIZE_PASS_BEGIN(CGPass, "cgp","cgp", false, false)
-INITIALIZE_AG_DEPENDENCY(CallGraph)
-INITIALIZE_PASS_END(CGPass, "cgp","cgp", false, false)
-INITIALIZE_PASS(FPass, "fp","fp", false, false)
-INITIALIZE_PASS_BEGIN(LPass, "lp","lp", false, false)
-INITIALIZE_PASS_DEPENDENCY(LoopInfo)
-INITIALIZE_PASS_END(LPass, "lp","lp", false, false)
-INITIALIZE_PASS(BPass, "bp","bp", false, false)
+}
diff --git a/unittests/IR/ValueTest.cpp b/unittests/IR/ValueTest.cpp
index 52efb1a..ebe23e8 100644
--- a/unittests/IR/ValueTest.cpp
+++ b/unittests/IR/ValueTest.cpp
@@ -43,4 +43,44 @@ TEST(ValueTest, UsedInBasicBlock) {
EXPECT_TRUE(F->arg_begin()->isUsedInBasicBlock(F->begin()));
}
+TEST(GlobalTest, CreateAddressSpace) {
+ LLVMContext &Ctx = getGlobalContext();
+ OwningPtr<Module> M(new Module("TestModule", Ctx));
+ Type *Int8Ty = Type::getInt8Ty(Ctx);
+ Type *Int32Ty = Type::getInt32Ty(Ctx);
+
+ GlobalVariable *Dummy0
+ = new GlobalVariable(*M,
+ Int32Ty,
+ true,
+ GlobalValue::ExternalLinkage,
+ Constant::getAllOnesValue(Int32Ty),
+ "dummy",
+ 0,
+ GlobalVariable::NotThreadLocal,
+ 1);
+
+ // Make sure the address space isn't dropped when returning this.
+ Constant *Dummy1 = M->getOrInsertGlobal("dummy", Int32Ty);
+ EXPECT_EQ(Dummy0, Dummy1);
+ EXPECT_EQ(1u, Dummy1->getType()->getPointerAddressSpace());
+
+
+ // This one requires a bitcast, but the address space must also stay the same.
+ GlobalVariable *DummyCast0
+ = new GlobalVariable(*M,
+ Int32Ty,
+ true,
+ GlobalValue::ExternalLinkage,
+ Constant::getAllOnesValue(Int32Ty),
+ "dummy_cast",
+ 0,
+ GlobalVariable::NotThreadLocal,
+ 1);
+
+ // Make sure the address space isn't dropped when returning this.
+ Constant *DummyCast1 = M->getOrInsertGlobal("dummy_cast", Int8Ty);
+ EXPECT_EQ(1u, DummyCast1->getType()->getPointerAddressSpace());
+ EXPECT_NE(DummyCast0, DummyCast1) << *DummyCast1;
+}
} // end anonymous namespace
diff --git a/unittests/IR/VerifierTest.cpp b/unittests/IR/VerifierTest.cpp
index 2848cb8..31936c3 100644
--- a/unittests/IR/VerifierTest.cpp
+++ b/unittests/IR/VerifierTest.cpp
@@ -24,10 +24,11 @@ namespace {
TEST(VerifierTest, Branch_i1) {
LLVMContext &C = getGlobalContext();
+ Module M("M", C);
FunctionType *FTy = FunctionType::get(Type::getVoidTy(C), /*isVarArg=*/false);
- OwningPtr<Function> F(Function::Create(FTy, GlobalValue::ExternalLinkage));
- BasicBlock *Entry = BasicBlock::Create(C, "entry", F.get());
- BasicBlock *Exit = BasicBlock::Create(C, "exit", F.get());
+ Function *F = cast<Function>(M.getOrInsertFunction("foo", FTy));
+ BasicBlock *Entry = BasicBlock::Create(C, "entry", F);
+ BasicBlock *Exit = BasicBlock::Create(C, "exit", F);
ReturnInst::Create(C, Exit);
// To avoid triggering an assertion in BranchInst::Create, we first create
diff --git a/unittests/IR/WaymarkTest.cpp b/unittests/IR/WaymarkTest.cpp
index cf7d76d..9a9b4a2 100644
--- a/unittests/IR/WaymarkTest.cpp
+++ b/unittests/IR/WaymarkTest.cpp
@@ -9,6 +9,7 @@
// we perform white-box tests
//
+#include "llvm/IR/Constants.h"
#include "llvm/IR/Function.h"
#include "llvm/IR/Instructions.h"
#include "llvm/IR/LLVMContext.h"
diff --git a/unittests/MC/CMakeLists.txt b/unittests/MC/CMakeLists.txt
new file mode 100644
index 0000000..0e4782c
--- /dev/null
+++ b/unittests/MC/CMakeLists.txt
@@ -0,0 +1,11 @@
+set(LLVM_LINK_COMPONENTS
+ MC
+ )
+
+set(MCSources
+ MCAtomTest.cpp
+ )
+
+add_llvm_unittest(MCTests
+ ${MCSources}
+ )
diff --git a/unittests/MC/MCAtomTest.cpp b/unittests/MC/MCAtomTest.cpp
new file mode 100644
index 0000000..17b056c
--- /dev/null
+++ b/unittests/MC/MCAtomTest.cpp
@@ -0,0 +1,31 @@
+//===- llvm/unittest/MC/MCAtomTest.cpp - Instructions unit tests ----------===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#include "llvm/MC/MCAtom.h"
+#include "llvm/MC/MCModule.h"
+#include "gtest/gtest.h"
+
+namespace llvm {
+namespace {
+
+TEST(MCAtomTest, MCDataSize) {
+ MCModule M;
+ MCDataAtom *Atom = M.createDataAtom(0, 0);
+ EXPECT_EQ(uint64_t(0), Atom->getEndAddr());
+ Atom->addData(0);
+ EXPECT_EQ(uint64_t(0), Atom->getEndAddr());
+ Atom->addData(1);
+ EXPECT_EQ(uint64_t(1), Atom->getEndAddr());
+ Atom->addData(2);
+ EXPECT_EQ(uint64_t(2), Atom->getEndAddr());
+ EXPECT_EQ(size_t(3), Atom->getData().size());
+}
+
+} // end anonymous namespace
+} // end namespace llvm
diff --git a/unittests/MC/Makefile b/unittests/MC/Makefile
new file mode 100644
index 0000000..4c25697
--- /dev/null
+++ b/unittests/MC/Makefile
@@ -0,0 +1,15 @@
+##===- unittests/IR/Makefile -------------------------------*- Makefile -*-===##
+#
+# The LLVM Compiler Infrastructure
+#
+# This file is distributed under the University of Illinois Open Source
+# License. See LICENSE.TXT for details.
+#
+##===----------------------------------------------------------------------===##
+
+LEVEL = ../..
+TESTNAME = MC
+LINK_COMPONENTS := MC
+
+include $(LEVEL)/Makefile.config
+include $(LLVM_SRC_ROOT)/unittests/Makefile.unittest
diff --git a/unittests/Makefile b/unittests/Makefile
index 36b82da..06ba932 100644
--- a/unittests/Makefile
+++ b/unittests/Makefile
@@ -9,8 +9,8 @@
LEVEL = ..
-PARALLEL_DIRS = ADT Analysis Bitcode DebugInfo ExecutionEngine IR Object \
- Option Support Transforms
+PARALLEL_DIRS = ADT Analysis Bitcode CodeGen DebugInfo ExecutionEngine IR \
+ MC Object Option Support Transforms
include $(LEVEL)/Makefile.common
diff --git a/unittests/Option/OptionParsingTest.cpp b/unittests/Option/OptionParsingTest.cpp
index 5a76d65..11d6d1e 100644
--- a/unittests/Option/OptionParsingTest.cpp
+++ b/unittests/Option/OptionParsingTest.cpp
@@ -20,7 +20,7 @@ using namespace llvm::opt;
enum ID {
OPT_INVALID = 0, // This is not an option ID.
#define OPTION(PREFIX, NAME, ID, KIND, GROUP, ALIAS, ALIASARGS, FLAGS, PARAM, \
- HELPTEXT, METAVAR) OPT_##ID,
+ HELPTEXT, METAVAR) OPT_##ID,
#include "Opts.inc"
LastOption
#undef OPTION
@@ -48,8 +48,8 @@ static const OptTable::Info InfoTable[] = {
namespace {
class TestOptTable : public OptTable {
public:
- TestOptTable()
- : OptTable(InfoTable, array_lengthof(InfoTable)) {}
+ TestOptTable(bool IgnoreCase = false)
+ : OptTable(InfoTable, array_lengthof(InfoTable), IgnoreCase) {}
};
}
@@ -157,15 +157,49 @@ TEST(Option, AliasArgs) {
EXPECT_EQ(AL->getAllArgValues(OPT_B)[1], "bar");
}
-TEST(Option, DashDash) {
+TEST(Option, IgnoreCase) {
+ TestOptTable T(true);
+ unsigned MAI, MAC;
+
+ const char *MyArgs[] = { "-a", "-joo" };
+ OwningPtr<InputArgList> AL(T.ParseArgs(MyArgs, array_endof(MyArgs), MAI, MAC));
+ EXPECT_TRUE(AL->hasArg(OPT_A));
+ EXPECT_TRUE(AL->hasArg(OPT_B));
+}
+
+TEST(Option, DoNotIgnoreCase) {
+ TestOptTable T;
+ unsigned MAI, MAC;
+
+ const char *MyArgs[] = { "-a", "-joo" };
+ OwningPtr<InputArgList> AL(T.ParseArgs(MyArgs, array_endof(MyArgs), MAI, MAC));
+ EXPECT_FALSE(AL->hasArg(OPT_A));
+ EXPECT_FALSE(AL->hasArg(OPT_B));
+}
+
+TEST(Option, SlurpEmpty) {
+ TestOptTable T;
+ unsigned MAI, MAC;
+
+ const char *MyArgs[] = { "-A", "-slurp" };
+ OwningPtr<InputArgList> AL(T.ParseArgs(MyArgs, array_endof(MyArgs), MAI, MAC));
+ EXPECT_TRUE(AL->hasArg(OPT_A));
+ EXPECT_TRUE(AL->hasArg(OPT_Slurp));
+ EXPECT_EQ(AL->getAllArgValues(OPT_Slurp).size(), 0U);
+}
+
+TEST(Option, Slurp) {
TestOptTable T;
unsigned MAI, MAC;
- const char *MyArgs[] = { "-A", "--", "-B", "--" };
+ const char *MyArgs[] = { "-A", "-slurp", "-B", "--", "foo" };
OwningPtr<InputArgList> AL(T.ParseArgs(MyArgs, array_endof(MyArgs), MAI, MAC));
+ EXPECT_EQ(AL->size(), 2U);
EXPECT_TRUE(AL->hasArg(OPT_A));
EXPECT_FALSE(AL->hasArg(OPT_B));
- EXPECT_EQ(AL->getAllArgValues(OPT_INPUT).size(), 2U);
- EXPECT_EQ(AL->getAllArgValues(OPT_INPUT)[0], "-B");
- EXPECT_EQ(AL->getAllArgValues(OPT_INPUT)[1], "--");
+ EXPECT_TRUE(AL->hasArg(OPT_Slurp));
+ EXPECT_EQ(AL->getAllArgValues(OPT_Slurp).size(), 3U);
+ EXPECT_EQ(AL->getAllArgValues(OPT_Slurp)[0], "-B");
+ EXPECT_EQ(AL->getAllArgValues(OPT_Slurp)[1], "--");
+ EXPECT_EQ(AL->getAllArgValues(OPT_Slurp)[2], "foo");
}
diff --git a/unittests/Option/Opts.td b/unittests/Option/Opts.td
index 986b312..aaed6b2 100644
--- a/unittests/Option/Opts.td
+++ b/unittests/Option/Opts.td
@@ -22,3 +22,5 @@ def I : Flag<["-"], "I">, Alias<H>, Group<my_group>;
def J : Flag<["-"], "J">, Alias<B>, AliasArgs<["foo"]>;
def Joo : Flag<["-"], "Joo">, Alias<B>, AliasArgs<["bar"]>;
+
+def Slurp : Option<["-"], "slurp", KIND_REMAINING_ARGS>;
diff --git a/unittests/Support/BlockFrequencyTest.cpp b/unittests/Support/BlockFrequencyTest.cpp
index ca420fc..ffdea2c 100644
--- a/unittests/Support/BlockFrequencyTest.cpp
+++ b/unittests/Support/BlockFrequencyTest.cpp
@@ -13,6 +13,11 @@ TEST(BlockFrequencyTest, OneToZero) {
BranchProbability Prob(UINT32_MAX - 1, UINT32_MAX);
Freq *= Prob;
EXPECT_EQ(Freq.getFrequency(), 0u);
+
+ Freq = BlockFrequency(1);
+ uint32_t Remainder = Freq.scale(Prob);
+ EXPECT_EQ(Freq.getFrequency(), 0u);
+ EXPECT_EQ(Remainder, UINT32_MAX - 1);
}
TEST(BlockFrequencyTest, OneToOne) {
@@ -20,6 +25,11 @@ TEST(BlockFrequencyTest, OneToOne) {
BranchProbability Prob(UINT32_MAX, UINT32_MAX);
Freq *= Prob;
EXPECT_EQ(Freq.getFrequency(), 1u);
+
+ Freq = BlockFrequency(1);
+ uint32_t Remainder = Freq.scale(Prob);
+ EXPECT_EQ(Freq.getFrequency(), 1u);
+ EXPECT_EQ(Remainder, 0u);
}
TEST(BlockFrequencyTest, ThreeToOne) {
@@ -27,6 +37,11 @@ TEST(BlockFrequencyTest, ThreeToOne) {
BranchProbability Prob(3000000, 9000000);
Freq *= Prob;
EXPECT_EQ(Freq.getFrequency(), 1u);
+
+ Freq = BlockFrequency(3);
+ uint32_t Remainder = Freq.scale(Prob);
+ EXPECT_EQ(Freq.getFrequency(), 1u);
+ EXPECT_EQ(Remainder, 0u);
}
TEST(BlockFrequencyTest, MaxToHalfMax) {
@@ -34,6 +49,11 @@ TEST(BlockFrequencyTest, MaxToHalfMax) {
BranchProbability Prob(UINT32_MAX / 2, UINT32_MAX);
Freq *= Prob;
EXPECT_EQ(Freq.getFrequency(), 9223372034707292159ULL);
+
+ Freq = BlockFrequency(UINT64_MAX);
+ uint32_t Remainder = Freq.scale(Prob);
+ EXPECT_EQ(Freq.getFrequency(), 9223372034707292159ULL);
+ EXPECT_EQ(Remainder, 0u);
}
TEST(BlockFrequencyTest, BigToBig) {
@@ -43,6 +63,11 @@ TEST(BlockFrequencyTest, BigToBig) {
BranchProbability Prob(P, P);
Freq *= Prob;
EXPECT_EQ(Freq.getFrequency(), Big);
+
+ Freq = BlockFrequency(Big);
+ uint32_t Remainder = Freq.scale(Prob);
+ EXPECT_EQ(Freq.getFrequency(), Big);
+ EXPECT_EQ(Remainder, 0u);
}
TEST(BlockFrequencyTest, MaxToMax) {
@@ -50,6 +75,114 @@ TEST(BlockFrequencyTest, MaxToMax) {
BranchProbability Prob(UINT32_MAX, UINT32_MAX);
Freq *= Prob;
EXPECT_EQ(Freq.getFrequency(), UINT64_MAX);
+
+ // This additionally makes sure if we have a value equal to our saturating
+ // value, we do not signal saturation if the result equals said value, but
+ // saturating does not occur.
+ Freq = BlockFrequency(UINT64_MAX);
+ uint32_t Remainder = Freq.scale(Prob);
+ EXPECT_EQ(Freq.getFrequency(), UINT64_MAX);
+ EXPECT_EQ(Remainder, 0u);
+}
+
+TEST(BlockFrequencyTest, ScaleResultRemainderTest) {
+ struct {
+ uint64_t Freq;
+ uint32_t Prob[2];
+ uint64_t ExpectedFreq;
+ uint32_t ExpectedRemainder;
+ } Tests[80] = {
+ // Data for scaling that results in <= 64 bit division.
+ { 0x1423e2a50ULL, { 0x64819521, 0x7765dd13 }, 0x10f418889ULL, 0x92b9d25 },
+ { 0x35ef14ceULL, { 0x28ade3c7, 0x304532ae }, 0x2d73c33aULL, 0x2c0fd0b6 },
+ { 0xd03dbfbe24ULL, { 0x790079, 0xe419f3 }, 0x6e776fc1fdULL, 0x4a06dd },
+ { 0x21d67410bULL, { 0x302a9dc2, 0x3ddb4442 }, 0x1a5948fd6ULL, 0x265d1c2a },
+ { 0x8664aeadULL, { 0x3d523513, 0x403523b1 }, 0x805a04cfULL, 0x324c27b8 },
+ { 0x201db0cf4ULL, { 0x35112a7b, 0x79fc0c74 }, 0xdf8b07f6ULL, 0x490c1dc4 },
+ { 0x13f1e4430aULL, { 0x21c92bf, 0x21e63aae }, 0x13e0cba15ULL, 0x1df47c30 },
+ { 0x16c83229ULL, { 0x3793f66f, 0x53180dea }, 0xf3ce7b6ULL, 0x1d0c1b6b },
+ { 0xc62415be8ULL, { 0x9cc4a63, 0x4327ae9b }, 0x1ce8b71caULL, 0x3f2c696a },
+ { 0x6fac5e434ULL, { 0xe5f9170, 0x1115e10b }, 0x5df23dd4cULL, 0x4dafc7c },
+ { 0x1929375f2ULL, { 0x3a851375, 0x76c08456 }, 0xc662b082ULL, 0x343589ee },
+ { 0x243c89db6ULL, { 0x354ebfc0, 0x450ef197 }, 0x1bf8c1661ULL, 0x4948e49 },
+ { 0x310e9b31aULL, { 0x1b1b8acf, 0x2d3629f0 }, 0x1d69c93f9ULL, 0x73e3b96 },
+ { 0xa1fae921dULL, { 0xa7a098c, 0x10469f44 }, 0x684413d6cULL, 0x86a882c },
+ { 0xc1582d957ULL, { 0x498e061, 0x59856bc }, 0x9edc5f4e7ULL, 0x29b0653 },
+ { 0x57cfee75ULL, { 0x1d061dc3, 0x7c8bfc17 }, 0x1476a220ULL, 0x2383d33f },
+ { 0x139220080ULL, { 0x294a6c71, 0x2a2b07c9 }, 0x1329e1c76ULL, 0x7aa5da },
+ { 0x1665d353cULL, { 0x7080db5, 0xde0d75c }, 0xb590d9fbULL, 0x7ba8c38 },
+ { 0xe8f14541ULL, { 0x5188e8b2, 0x736527ef }, 0xa4971be5ULL, 0x6b612167 },
+ { 0x2f4775f29ULL, { 0x254ef0fe, 0x435fcf50 }, 0x1a2e449c1ULL, 0x28bbf5e },
+ { 0x27b85d8d7ULL, { 0x304c8220, 0x5de678f2 }, 0x146e3bef9ULL, 0x4b27097e },
+ { 0x1d362e36bULL, { 0x36c85b12, 0x37a66f55 }, 0x1cc19b8e6ULL, 0x688e828 },
+ { 0x155fd48c7ULL, { 0xf5894d, 0x1256108 }, 0x11e383602ULL, 0x111f0cb },
+ { 0xb5db2d15ULL, { 0x39bb26c5, 0x5bdcda3e }, 0x72499259ULL, 0x59c4939b },
+ { 0x153990298ULL, { 0x48921c09, 0x706eb817 }, 0xdb3268e8ULL, 0x66bb8a80 },
+ { 0x28a7c3ed7ULL, { 0x1f776fd7, 0x349f7a70 }, 0x184f73ae1ULL, 0x28910321 },
+ { 0x724dbeabULL, { 0x1bd149f5, 0x253a085e }, 0x5569c0b3ULL, 0xff8e2ed },
+ { 0xd8f0c513ULL, { 0x18c8cc4c, 0x1b72bad0 }, 0xc3e30643ULL, 0xd85e134 },
+ { 0x17ce3dcbULL, { 0x1e4c6260, 0x233b359e }, 0x1478f4afULL, 0x49ea31e },
+ { 0x1ce036ce0ULL, { 0x29e3c8af, 0x5318dd4a }, 0xe8e76196ULL, 0x11d5b9c4 },
+ { 0x1473ae2aULL, { 0x29b897ba, 0x2be29378 }, 0x13718185ULL, 0x6f93b2c },
+ { 0x1dd41aa68ULL, { 0x3d0a4441, 0x5a0e8f12 }, 0x1437b6bbfULL, 0x54b09ffa },
+ { 0x1b49e4a53ULL, { 0x3430c1fe, 0x5a204aed }, 0xfcd6852fULL, 0x15ad6ed7 },
+ { 0x217941b19ULL, { 0x12ced2bd, 0x21b68310 }, 0x12aca65b1ULL, 0x1b2a9565 },
+ { 0xac6a4dc8ULL, { 0x3ed68da8, 0x6fdca34c }, 0x60da926dULL, 0x22ff53e4 },
+ { 0x1c503a4e7ULL, { 0xfcbbd32, 0x11e48d17 }, 0x18fec7d38ULL, 0xa8aa816 },
+ { 0x1c885855ULL, { 0x213e919d, 0x25941897 }, 0x193de743ULL, 0x4ea09c },
+ { 0x29b9c168eULL, { 0x2b644aea, 0x45725ee7 }, 0x1a122e5d5ULL, 0xbee1099 },
+ { 0x806a33f2ULL, { 0x30a80a23, 0x5063733a }, 0x4db9a264ULL, 0x1eaed76e },
+ { 0x282afc96bULL, { 0x143ae554, 0x1a9863ff }, 0x1e8de5204ULL, 0x158d9020 },
+ // Data for scaling that results in > 64 bit division.
+ { 0x23ca5f2f672ca41cULL, { 0xecbc641, 0x111373f7 }, 0x1f0301e5e8295ab5ULL, 0xf627f79 },
+ { 0x5e4f2468142265e3ULL, { 0x1ddf5837, 0x32189233 }, 0x383ca7ba9fdd2c8cULL, 0x1c8f33e1 },
+ { 0x277a1a6f6b266bf6ULL, { 0x415d81a8, 0x61eb5e1e }, 0x1a5a3e1d41b30c0fULL, 0x29cde3ae },
+ { 0x1bdbb49a237035cbULL, { 0xea5bf17, 0x1d25ffb3 }, 0xdffc51c53d44b93ULL, 0x5170574 },
+ { 0x2bce6d29b64fb8ULL, { 0x3bfd5631, 0x7525c9bb }, 0x166ebedda7ac57ULL, 0x3026dfab },
+ { 0x3a02116103df5013ULL, { 0x2ee18a83, 0x3299aea8 }, 0x35be8922ab1e2a84ULL, 0x298d9919 },
+ { 0x7b5762390799b18cULL, { 0x12f8e5b9, 0x2563bcd4 }, 0x3e960077aca01209ULL, 0x93afeb8 },
+ { 0x69cfd72537021579ULL, { 0x4c35f468, 0x6a40feee }, 0x4be4cb3848be98a3ULL, 0x4ff96b9e },
+ { 0x49dfdf835120f1c1ULL, { 0x8cb3759, 0x559eb891 }, 0x79663f7120edadeULL, 0x51b1fb5b },
+ { 0x74b5be5c27676381ULL, { 0x47e4c5e0, 0x7c7b19ff }, 0x4367d2dff36a1028ULL, 0x7a7b5608 },
+ { 0x4f50f97075e7f431ULL, { 0x9a50a17, 0x11cd1185 }, 0x2af952b34c032df4ULL, 0xfddc6a3 },
+ { 0x2f8b0d712e393be4ULL, { 0x1487e386, 0x15aa356e }, 0x2d0df36478a776aaULL, 0x14e2564c },
+ { 0x224c1c75999d3deULL, { 0x3b2df0ea, 0x4523b100 }, 0x1d5b481d145f08aULL, 0x15145eec },
+ { 0x2bcbcea22a399a76ULL, { 0x28b58212, 0x48dd013e }, 0x187814d084c47cabULL, 0x3a38ebe2 },
+ { 0x1dbfca91257cb2d1ULL, { 0x1a8c04d9, 0x5e92502c }, 0x859cf7d00f77545ULL, 0x7431f4d },
+ { 0x7f20039b57cda935ULL, { 0xeccf651, 0x323f476e }, 0x25720cd976461a77ULL, 0x202817a3 },
+ { 0x40512c6a586aa087ULL, { 0x113b0423, 0x398c9eab }, 0x1341c03de8696a7eULL, 0x1e27284b },
+ { 0x63d802693f050a11ULL, { 0xf50cdd6, 0xfce2a44 }, 0x60c0177bb5e46846ULL, 0xf7ad89e },
+ { 0x2d956b422838de77ULL, { 0xb2d345b, 0x1321e557 }, 0x1aa0ed16b6aa5319ULL, 0xfe1a5ce },
+ { 0x5a1cdf0c1657bc91ULL, { 0x1d77bb0c, 0x1f991ff1 }, 0x54097ee94ff87560ULL, 0x11c4a26c },
+ { 0x3801b26d7e00176bULL, { 0xeed25da, 0x1a819d8b }, 0x1f89e96a3a639526ULL, 0xcd51e7c },
+ { 0x37655e74338e1e45ULL, { 0x300e170a, 0x5a1595fe }, 0x1d8cfb55fddc0441ULL, 0x3df05434 },
+ { 0x7b38703f2a84e6ULL, { 0x66d9053, 0xc79b6b9 }, 0x3f7d4c91774094ULL, 0x26d939e },
+ { 0x2245063c0acb3215ULL, { 0x30ce2f5b, 0x610e7271 }, 0x113b916468389235ULL, 0x1b588512 },
+ { 0x6bc195877b7b8a7eULL, { 0x392004aa, 0x4a24e60c }, 0x530594fb17db6ba5ULL, 0x35c0a5f0 },
+ { 0x40a3fde23c7b43dbULL, { 0x4e712195, 0x6553e56e }, 0x320a799bc76a466aULL, 0x5e23a5eb },
+ { 0x1d3dfc2866fbccbaULL, { 0x5075b517, 0x5fc42245 }, 0x18917f0061595bc3ULL, 0x3fcf4527 },
+ { 0x19aeb14045a61121ULL, { 0x1bf6edec, 0x707e2f4b }, 0x6626672a070bcc7ULL, 0x3607801f },
+ { 0x44ff90486c531e9fULL, { 0x66598a, 0x8a90dc }, 0x32f6f2b0525199b0ULL, 0x5ab576 },
+ { 0x3f3e7121092c5bcbULL, { 0x1c754df7, 0x5951a1b9 }, 0x14267f50b7ef375dULL, 0x221220a8 },
+ { 0x60e2dafb7e50a67eULL, { 0x4d96c66e, 0x65bd878d }, 0x49e31715ac393f8bULL, 0x4e97b195 },
+ { 0x656286667e0e6e29ULL, { 0x9d971a2, 0xacda23b }, 0x5c6ee315ead6cb4fULL, 0x516f5bd },
+ { 0x1114e0974255d507ULL, { 0x1c693, 0x2d6ff }, 0xaae42e4b35f6e60ULL, 0x8b65 },
+ { 0x508c8baf3a70ff5aULL, { 0x3b26b779, 0x6ad78745 }, 0x2c98387636c4b365ULL, 0x11dc6a51 },
+ { 0x5b47bc666bf1f9cfULL, { 0x10a87ed6, 0x187d358a }, 0x3e1767155848368bULL, 0xfb871c },
+ { 0x50954e3744460395ULL, { 0x7a42263, 0xcdaa048 }, 0x2fe739f0aee1fee1ULL, 0xb8add57 },
+ { 0x20020b406550dd8fULL, { 0x3318539, 0x42eead0 }, 0x186f326325fa346bULL, 0x10d3ae7 },
+ { 0x5bcb0b872439ffd5ULL, { 0x6f61fb2, 0x9af7344 }, 0x41fa1e3bec3c1b30ULL, 0x4fee45a },
+ { 0x7a670f365db87a53ULL, { 0x417e102, 0x3bb54c67 }, 0x8642a558304fd9eULL, 0x3b65f514 },
+ { 0x1ef0db1e7bab1cd0ULL, { 0x2b60cf38, 0x4188f78f }, 0x147ae0d6226b2ee6ULL, 0x336b6106 }
+ };
+
+ for (unsigned i = 0; i < 80; i++) {
+ BlockFrequency Freq(Tests[i].Freq);
+ uint32_t Remainder = Freq.scale(BranchProbability(Tests[i].Prob[0],
+ Tests[i].Prob[1]));
+ EXPECT_EQ(Tests[i].ExpectedFreq, Freq.getFrequency());
+ EXPECT_EQ(Tests[i].ExpectedRemainder, Remainder);
+ }
}
TEST(BlockFrequency, Divide) {
diff --git a/unittests/Support/CMakeLists.txt b/unittests/Support/CMakeLists.txt
index 197561e..0abc2ff 100644
--- a/unittests/Support/CMakeLists.txt
+++ b/unittests/Support/CMakeLists.txt
@@ -17,9 +17,7 @@ add_llvm_unittest(SupportTests
EndianTest.cpp
ErrorOrTest.cpp
FileOutputBufferTest.cpp
- IntegersSubsetTest.cpp
LeakDetectorTest.cpp
- LocaleTest.cpp
LockFileManagerTest.cpp
ManagedStatic.cpp
MathExtrasTest.cpp
@@ -30,8 +28,11 @@ add_llvm_unittest(SupportTests
ProcessTest.cpp
ProgramTest.cpp
RegexTest.cpp
+ SourceMgrTest.cpp
SwapByteOrderTest.cpp
+ ThreadLocalTest.cpp
TimeValueTest.cpp
+ UnicodeTest.cpp
ValueHandleTest.cpp
YAMLIOTest.cpp
YAMLParserTest.cpp
diff --git a/unittests/Support/CompressionTest.cpp b/unittests/Support/CompressionTest.cpp
index c8e2cd9..c0a9ada 100644
--- a/unittests/Support/CompressionTest.cpp
+++ b/unittests/Support/CompressionTest.cpp
@@ -63,6 +63,12 @@ TEST(CompressionTest, Zlib) {
TestZlibCompression(BinaryDataStr, zlib::DefaultCompression);
}
+TEST(CompressionTest, ZlibCRC32) {
+ EXPECT_EQ(
+ 0x414FA339U,
+ zlib::crc32(StringRef("The quick brown fox jumps over the lazy dog")));
+}
+
#endif
}
diff --git a/unittests/Support/ConstantRangeTest.cpp b/unittests/Support/ConstantRangeTest.cpp
index 4d6bbf6..3e0a085 100644
--- a/unittests/Support/ConstantRangeTest.cpp
+++ b/unittests/Support/ConstantRangeTest.cpp
@@ -216,6 +216,9 @@ TEST_F(ConstantRangeTest, SExt) {
EXPECT_EQ(ConstantRange(APInt(8, 120), APInt(8, 140)).signExtend(16),
ConstantRange(APInt(16, -128), APInt(16, 128)));
+
+ EXPECT_EQ(ConstantRange(APInt(16, 0x0200), APInt(16, 0x8000)).signExtend(19),
+ ConstantRange(APInt(19, 0x0200), APInt(19, 0x8000)));
}
TEST_F(ConstantRangeTest, IntersectWith) {
diff --git a/unittests/Support/ErrorOrTest.cpp b/unittests/Support/ErrorOrTest.cpp
index 4853426..feb6a08 100644
--- a/unittests/Support/ErrorOrTest.cpp
+++ b/unittests/Support/ErrorOrTest.cpp
@@ -45,9 +45,6 @@ TEST(ErrorOr, Types) {
*a = 42;
EXPECT_EQ(42, x);
- EXPECT_FALSE(ErrorOr<void>(errc::broken_pipe));
- EXPECT_TRUE(ErrorOr<void>(errc::success));
-
#if LLVM_HAS_CXX11_STDLIB
// Move only types.
EXPECT_EQ(3, **t3());
@@ -67,38 +64,3 @@ TEST(ErrorOr, Covariant) {
#endif
}
} // end anon namespace
-
-struct InvalidArgError {
- InvalidArgError() {}
- InvalidArgError(std::string S) : ArgName(S) {}
- std::string ArgName;
-};
-
-namespace llvm {
-template<>
-struct ErrorOrUserDataTraits<InvalidArgError> : true_type {
- static error_code error() {
- return make_error_code(errc::invalid_argument);
- }
-};
-} // end namespace llvm
-
-ErrorOr<int> t4() {
- return InvalidArgError("adena");
-}
-
-ErrorOr<void> t5() {
- return InvalidArgError("pie");
-}
-
-namespace {
-TEST(ErrorOr, UserErrorData) {
- ErrorOr<int> a = t4();
- EXPECT_EQ(errc::invalid_argument, a);
- EXPECT_EQ("adena", t4().getError<InvalidArgError>().ArgName);
-
- ErrorOr<void> b = t5();
- EXPECT_EQ(errc::invalid_argument, b);
- EXPECT_EQ("pie", b.getError<InvalidArgError>().ArgName);
-}
-} // end anon namespace
diff --git a/unittests/Support/IntegersSubsetTest.cpp b/unittests/Support/IntegersSubsetTest.cpp
deleted file mode 100644
index f4298bf..0000000
--- a/unittests/Support/IntegersSubsetTest.cpp
+++ /dev/null
@@ -1,326 +0,0 @@
-//===- llvm/unittest/Support/IntegersSubsetTest.cpp - IntegersSubset tests ===//
-//
-// The LLVM Compiler Infrastructure
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
-//
-//===----------------------------------------------------------------------===//
-
-#include "llvm/Support/IntegersSubset.h"
-#include "llvm/ADT/APInt.h"
-#include "llvm/Support/IntegersSubsetMapping.h"
-#include "gtest/gtest.h"
-#include <vector>
-
-using namespace llvm;
-
-namespace {
-
- class Int : public APInt {
- public:
- Int() {}
- Int(uint64_t V) : APInt(64, V) {}
- Int(const APInt& Src) : APInt(Src) {}
- bool operator < (const APInt& RHS) const { return ult(RHS); }
- bool operator > (const APInt& RHS) const { return ugt(RHS); }
- bool operator <= (const APInt& RHS) const { return ule(RHS); }
- bool operator >= (const APInt& RHS) const { return uge(RHS); }
- };
-
- typedef IntRange<Int> Range;
- typedef IntegersSubsetGeneric<Int> Subset;
- typedef IntegersSubsetMapping<unsigned,Subset,Int> Mapping;
-
- TEST(IntegersSubsetTest, GeneralTest) {
-
- // Test construction.
-
- std::vector<Range> Ranges;
- Ranges.reserve(3);
-
- // Initialize Subset as union of three pairs:
- // { {0, 8}, {10, 18}, {20, 28} }
- for (unsigned i = 0; i < 3; ++i)
- Ranges.push_back(Range(Int(i*10), Int(i*10 + 8)));
-
- Subset TheSubset(Ranges);
-
- for (unsigned i = 0; i < 3; ++i) {
- EXPECT_EQ(TheSubset.getItem(i).getLow(), Int(i*10));
- EXPECT_EQ(TheSubset.getItem(i).getHigh(), Int(i*10 + 8));
- }
-
- EXPECT_EQ(TheSubset.getNumItems(), 3ULL);
-
- // Test belonging to range.
-
- EXPECT_TRUE(TheSubset.isSatisfies(Int(5)));
- EXPECT_FALSE(TheSubset.isSatisfies(Int(9)));
-
- // Test when subset contains the only item.
-
- Ranges.clear();
- Ranges.push_back(Range(Int(10), Int(10)));
-
- Subset TheSingleNumber(Ranges);
-
- EXPECT_TRUE(TheSingleNumber.isSingleNumber());
-
- Ranges.push_back(Range(Int(12), Int(15)));
-
- Subset NotASingleNumber(Ranges);
-
- EXPECT_FALSE(NotASingleNumber.isSingleNumber());
-
- // Test when subset contains items that are not a ranges but
- // the single numbers.
-
- Ranges.clear();
- Ranges.push_back(Range(Int(10), Int(10)));
- Ranges.push_back(Range(Int(15), Int(19)));
-
- Subset WithSingleNumberItems(Ranges);
-
- EXPECT_TRUE(WithSingleNumberItems.isSingleNumber(0));
- EXPECT_FALSE(WithSingleNumberItems.isSingleNumber(1));
-
- // Test size of subset. Note subset itself may be not optimized (improper),
- // so it may contain duplicates, and the size of subset { {0, 9} {5, 9} }
- // will 15 instead of 10.
-
- Ranges.clear();
- Ranges.push_back(Range(Int(0), Int(9)));
- Ranges.push_back(Range(Int(5), Int(9)));
-
- Subset NotOptimizedSubset(Ranges);
-
- EXPECT_EQ(NotOptimizedSubset.getSize(), 15ULL);
-
- // Test access to a single value.
- // getSingleValue(idx) method represents subset as flat numbers collection,
- // so subset { {0, 3}, {8, 10} } will represented as array
- // { 0, 1, 2, 3, 8, 9, 10 }.
-
- Ranges.clear();
- Ranges.push_back(Range(Int(0), Int(3)));
- Ranges.push_back(Range(Int(8), Int(10)));
-
- Subset OneMoreSubset(Ranges);
-
- EXPECT_EQ(OneMoreSubset.getSingleValue(5), Int(9));
- }
-
- TEST(IntegersSubsetTest, MappingTest) {
-
- Mapping::Cases TheCases;
-
- unsigned Successors[3] = {0, 1, 2};
-
- // Test construction.
-
- Mapping TheMapping;
- for (unsigned i = 0; i < 3; ++i)
- TheMapping.add(Int(10*i), Int(10*i + 9), Successors + i);
- TheMapping.add(Int(111), Int(222), Successors);
- TheMapping.removeItem(--TheMapping.end());
-
- TheMapping.getCases(TheCases);
-
- EXPECT_EQ(TheCases.size(), 3ULL);
-
- for (unsigned i = 0; i < 3; ++i) {
- Mapping::Cases::iterator CaseIt = TheCases.begin();
- std::advance(CaseIt, i);
- EXPECT_EQ(CaseIt->first, Successors + i);
- EXPECT_EQ(CaseIt->second.getNumItems(), 1ULL);
- EXPECT_EQ(CaseIt->second.getItem(0), Range(Int(10*i), Int(10*i + 9)));
- }
-
- // Test verification.
-
- Mapping ImproperMapping;
- ImproperMapping.add(Int(10), Int(11), Successors + 0);
- ImproperMapping.add(Int(11), Int(12), Successors + 1);
-
- Mapping::RangeIterator ErrItem;
- EXPECT_FALSE(ImproperMapping.verify(ErrItem));
- EXPECT_EQ(ErrItem, --ImproperMapping.end());
-
- Mapping ProperMapping;
- ProperMapping.add(Int(10), Int(11), Successors + 0);
- ProperMapping.add(Int(12), Int(13), Successors + 1);
-
- EXPECT_TRUE(ProperMapping.verify(ErrItem));
-
- // Test optimization.
-
- Mapping ToBeOptimized;
-
- for (unsigned i = 0; i < 3; ++i) {
- ToBeOptimized.add(Int(i * 10), Int(i * 10 + 1), Successors + i);
- ToBeOptimized.add(Int(i * 10 + 2), Int(i * 10 + 9), Successors + i);
- }
-
- ToBeOptimized.optimize();
-
- TheCases.clear();
- ToBeOptimized.getCases(TheCases);
-
- EXPECT_EQ(TheCases.size(), 3ULL);
-
- for (unsigned i = 0; i < 3; ++i) {
- Mapping::Cases::iterator CaseIt = TheCases.begin();
- std::advance(CaseIt, i);
- EXPECT_EQ(CaseIt->first, Successors + i);
- EXPECT_EQ(CaseIt->second.getNumItems(), 1ULL);
- EXPECT_EQ(CaseIt->second.getItem(0), Range(Int(i * 10), Int(i * 10 + 9)));
- }
- }
-
- typedef unsigned unsigned_pair[2];
- typedef unsigned_pair unsigned_ranges[];
-
- void TestDiff(
- const unsigned_ranges LHS,
- unsigned LSize,
- const unsigned_ranges RHS,
- unsigned RSize,
- const unsigned_ranges ExcludeRes,
- unsigned ExcludeResSize,
- const unsigned_ranges IntersectRes,
- unsigned IntersectResSize
- ) {
-
- Mapping::RangesCollection Ranges;
-
- Mapping LHSMapping;
- for (unsigned i = 0; i < LSize; ++i)
- Ranges.push_back(Range(Int(LHS[i][0]), Int(LHS[i][1])));
- LHSMapping.add(Ranges);
-
- Ranges.clear();
-
- Mapping RHSMapping;
- for (unsigned i = 0; i < RSize; ++i)
- Ranges.push_back(Range(Int(RHS[i][0]), Int(RHS[i][1])));
- RHSMapping.add(Ranges);
-
- Mapping LExclude, Intersection;
-
- LHSMapping.diff(&LExclude, &Intersection, 0, RHSMapping);
-
- if (ExcludeResSize) {
- EXPECT_EQ(LExclude.size(), ExcludeResSize);
-
- unsigned i = 0;
- for (Mapping::RangeIterator rei = LExclude.begin(),
- e = LExclude.end(); rei != e; ++rei, ++i)
- EXPECT_EQ(rei->first, Range(ExcludeRes[i][0], ExcludeRes[i][1]));
- } else
- EXPECT_TRUE(LExclude.empty());
-
- if (IntersectResSize) {
- EXPECT_EQ(Intersection.size(), IntersectResSize);
-
- unsigned i = 0;
- for (Mapping::RangeIterator ii = Intersection.begin(),
- e = Intersection.end(); ii != e; ++ii, ++i)
- EXPECT_EQ(ii->first, Range(IntersectRes[i][0], IntersectRes[i][1]));
- } else
- EXPECT_TRUE(Intersection.empty());
-
- LExclude.clear();
- Intersection.clear();
- RHSMapping.diff(0, &Intersection, &LExclude, LHSMapping);
-
- // Check LExclude again.
- if (ExcludeResSize) {
- EXPECT_EQ(LExclude.size(), ExcludeResSize);
-
- unsigned i = 0;
- for (Mapping::RangeIterator rei = LExclude.begin(),
- e = LExclude.end(); rei != e; ++rei, ++i)
- EXPECT_EQ(rei->first, Range(ExcludeRes[i][0], ExcludeRes[i][1]));
- } else
- EXPECT_TRUE(LExclude.empty());
- }
-
- TEST(IntegersSubsetTest, DiffTest) {
-
- static const unsigned NOT_A_NUMBER = 0xffff;
-
- {
- unsigned_ranges LHS = { { 0, 4 }, { 7, 10 }, { 13, 17 } };
- unsigned_ranges RHS = { { 3, 14 } };
- unsigned_ranges ExcludeRes = { { 0, 2 }, { 15, 17 } };
- unsigned_ranges IntersectRes = { { 3, 4 }, { 7, 10 }, { 13, 14 } };
-
- TestDiff(LHS, 3, RHS, 1, ExcludeRes, 2, IntersectRes, 3);
- }
-
- {
- unsigned_ranges LHS = { { 0, 4 }, { 7, 10 }, { 13, 17 } };
- unsigned_ranges RHS = { { 0, 4 }, { 13, 17 } };
- unsigned_ranges ExcludeRes = { { 7, 10 } };
- unsigned_ranges IntersectRes = { { 0, 4 }, { 13, 17 } };
-
- TestDiff(LHS, 3, RHS, 2, ExcludeRes, 1, IntersectRes, 2);
- }
-
- {
- unsigned_ranges LHS = { { 0, 17 } };
- unsigned_ranges RHS = { { 1, 5 }, { 10, 12 }, { 15, 16 } };
- unsigned_ranges ExcludeRes =
- { { 0, 0 }, { 6, 9 }, { 13, 14 }, { 17, 17 } };
- unsigned_ranges IntersectRes = { { 1, 5 }, { 10, 12 }, { 15, 16 } };
-
- TestDiff(LHS, 1, RHS, 3, ExcludeRes, 4, IntersectRes, 3);
- }
-
- {
- unsigned_ranges LHS = { { 2, 4 } };
- unsigned_ranges RHS = { { 0, 5 } };
- unsigned_ranges ExcludeRes = { {NOT_A_NUMBER, NOT_A_NUMBER} };
- unsigned_ranges IntersectRes = { { 2, 4 } };
-
- TestDiff(LHS, 1, RHS, 1, ExcludeRes, 0, IntersectRes, 1);
- }
-
- {
- unsigned_ranges LHS = { { 2, 4 } };
- unsigned_ranges RHS = { { 7, 8 } };
- unsigned_ranges ExcludeRes = { { 2, 4 } };
- unsigned_ranges IntersectRes = { {NOT_A_NUMBER, NOT_A_NUMBER} };
-
- TestDiff(LHS, 1, RHS, 1, ExcludeRes, 1, IntersectRes, 0);
- }
-
- {
- unsigned_ranges LHS = { { 3, 7 } };
- unsigned_ranges RHS = { { 1, 4 } };
- unsigned_ranges ExcludeRes = { { 5, 7 } };
- unsigned_ranges IntersectRes = { { 3, 4 } };
-
- TestDiff(LHS, 1, RHS, 1, ExcludeRes, 1, IntersectRes, 1);
- }
-
- {
- unsigned_ranges LHS = { { 0, 7 } };
- unsigned_ranges RHS = { { 0, 5 }, { 6, 9 } };
- unsigned_ranges ExcludeRes = { {NOT_A_NUMBER, NOT_A_NUMBER} };
- unsigned_ranges IntersectRes = { { 0, 5 }, {6, 7} };
-
- TestDiff(LHS, 1, RHS, 2, ExcludeRes, 0, IntersectRes, 2);
- }
-
- {
- unsigned_ranges LHS = { { 17, 17 } };
- unsigned_ranges RHS = { { 4, 4 } };
- unsigned_ranges ExcludeRes = { {17, 17} };
- unsigned_ranges IntersectRes = { { NOT_A_NUMBER, NOT_A_NUMBER } };
-
- TestDiff(LHS, 1, RHS, 1, ExcludeRes, 1, IntersectRes, 0);
- }
- }
-}
diff --git a/unittests/Support/LocaleTest.cpp b/unittests/Support/LocaleTest.cpp
deleted file mode 100644
index 3524b4b..0000000
--- a/unittests/Support/LocaleTest.cpp
+++ /dev/null
@@ -1,100 +0,0 @@
-//===- unittests/Support/LocaleTest.cpp - Locale.h tests ------------------===//
-//
-// The LLVM Compiler Infrastructure
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
-//
-//===----------------------------------------------------------------------===//
-
-#include "llvm/Support/Locale.h"
-#include "gtest/gtest.h"
-
-namespace llvm {
-namespace sys {
-namespace locale {
-namespace {
-
-// FIXME: WIN32 implementation is incorrect. We should consider using the one
-// from LocaleGeneric.inc for WIN32.
-#ifndef _WIN32
-TEST(Locale, columnWidth) {
- // FIXME: This test fails with MacOSX implementation of columnWidth.
-#ifndef __APPLE__
- EXPECT_EQ(0, columnWidth(""));
- EXPECT_EQ(1, columnWidth(" "));
- EXPECT_EQ(1, columnWidth("a"));
- EXPECT_EQ(1, columnWidth("~"));
-
- EXPECT_EQ(6, columnWidth("abcdef"));
-
- EXPECT_EQ(-1, columnWidth("\x01"));
- EXPECT_EQ(-1, columnWidth("aaaaaaaaaa\x01"));
- EXPECT_EQ(-1, columnWidth("\342\200\213")); // 200B ZERO WIDTH SPACE
-
- EXPECT_EQ(0, columnWidth("\314\200")); // 0300 COMBINING GRAVE ACCENT
- EXPECT_EQ(1, columnWidth("\340\270\201")); // 0E01 THAI CHARACTER KO KAI
- EXPECT_EQ(2, columnWidth("\344\270\200")); // CJK UNIFIED IDEOGRAPH-4E00
-
- EXPECT_EQ(4, columnWidth("\344\270\200\344\270\200"));
- EXPECT_EQ(3, columnWidth("q\344\270\200"));
- EXPECT_EQ(3, columnWidth("\314\200\340\270\201\344\270\200"));
-
- // Invalid UTF-8 strings, columnWidth should error out.
- EXPECT_EQ(-2, columnWidth("\344"));
- EXPECT_EQ(-2, columnWidth("\344\270"));
- EXPECT_EQ(-2, columnWidth("\344\270\033"));
- EXPECT_EQ(-2, columnWidth("\344\270\300"));
- EXPECT_EQ(-2, columnWidth("\377\366\355"));
-
- EXPECT_EQ(-2, columnWidth("qwer\344"));
- EXPECT_EQ(-2, columnWidth("qwer\344\270"));
- EXPECT_EQ(-2, columnWidth("qwer\344\270\033"));
- EXPECT_EQ(-2, columnWidth("qwer\344\270\300"));
- EXPECT_EQ(-2, columnWidth("qwer\377\366\355"));
-
- // UTF-8 sequences longer than 4 bytes correspond to unallocated Unicode
- // characters.
- EXPECT_EQ(-2, columnWidth("\370\200\200\200\200")); // U+200000
- EXPECT_EQ(-2, columnWidth("\374\200\200\200\200\200")); // U+4000000
-#endif // __APPLE__
-}
-
-TEST(Locale, isPrint) {
- EXPECT_EQ(false, isPrint(0)); // <control-0000>-<control-001F>
- EXPECT_EQ(false, isPrint(0x01));
- EXPECT_EQ(false, isPrint(0x1F));
- EXPECT_EQ(true, isPrint(' '));
- EXPECT_EQ(true, isPrint('A'));
- EXPECT_EQ(true, isPrint('~'));
- EXPECT_EQ(false, isPrint(0x7F)); // <control-007F>..<control-009F>
- EXPECT_EQ(false, isPrint(0x90));
- EXPECT_EQ(false, isPrint(0x9F));
-
- EXPECT_EQ(true, isPrint(0xAC));
- // FIXME: Figure out if we want to treat SOFT HYPHEN as printable character.
-#ifndef __APPLE__
- EXPECT_EQ(false, isPrint(0xAD)); // SOFT HYPHEN
-#endif // __APPLE__
- EXPECT_EQ(true, isPrint(0xAE));
-
- // MacOS implementation doesn't think it's printable.
-#ifndef __APPLE__
- EXPECT_EQ(true, isPrint(0x0377)); // GREEK SMALL LETTER PAMPHYLIAN DIGAMMA
-#endif // __APPLE__
- EXPECT_EQ(false, isPrint(0x0378)); // <reserved-0378>..<reserved-0379>
-
- EXPECT_EQ(false, isPrint(0x0600)); // ARABIC NUMBER SIGN
-
- EXPECT_EQ(false, isPrint(0x1FFFF)); // <reserved-1F774>..<noncharacter-1FFFF>
- EXPECT_EQ(true, isPrint(0x20000)); // CJK UNIFIED IDEOGRAPH-20000
-
- EXPECT_EQ(false, isPrint(0x10FFFF)); // noncharacter
-}
-
-#endif // _WIN32
-
-} // namespace
-} // namespace locale
-} // namespace sys
-} // namespace llvm
diff --git a/unittests/Support/MemoryBufferTest.cpp b/unittests/Support/MemoryBufferTest.cpp
index de1dbb7..2b8806c 100644
--- a/unittests/Support/MemoryBufferTest.cpp
+++ b/unittests/Support/MemoryBufferTest.cpp
@@ -65,6 +65,28 @@ TEST_F(MemoryBufferTest, get) {
EXPECT_EQ("this is some data", data);
}
+TEST_F(MemoryBufferTest, NullTerminator4K) {
+ // Test that a file with size that is a multiple of the page size can be null
+ // terminated correctly by MemoryBuffer.
+ int TestFD;
+ SmallString<64> TestPath;
+ sys::fs::createTemporaryFile("MemoryBufferTest_NullTerminator4K", "temp",
+ TestFD, TestPath);
+ raw_fd_ostream OF(TestFD, true, /*unbuffered=*/true);
+ for (unsigned i = 0; i < 4096 / 16; ++i) {
+ OF << "0123456789abcdef";
+ }
+ OF.close();
+
+ OwningPtr<MemoryBuffer> MB;
+ error_code EC = MemoryBuffer::getFile(TestPath.c_str(), MB);
+ ASSERT_FALSE(EC);
+
+ const char *BufData = MB->getBufferStart();
+ EXPECT_EQ('f', BufData[4095]);
+ EXPECT_EQ('\0', BufData[4096]);
+}
+
TEST_F(MemoryBufferTest, copy) {
// copy with no name
OwningBuffer MBC1(MemoryBuffer::getMemBufferCopy(data));
@@ -112,7 +134,7 @@ void MemoryBufferTest::testGetOpenFileSlice(bool Reopen) {
SmallString<64> TestPath;
// Create a temporary file and write data into it.
sys::fs::createTemporaryFile("prefix", "temp", TestFD, TestPath);
- // OF is responsible for closing the file; If the file is not
+ // OF is responsible for closing the file; If the file is not
// reopened, it will be unbuffered so that the results are
// immediately visible through the fd.
raw_fd_ostream OF(TestFD, true, !Reopen);
@@ -128,7 +150,7 @@ void MemoryBufferTest::testGetOpenFileSlice(bool Reopen) {
OwningBuffer Buf;
error_code EC = MemoryBuffer::getOpenFileSlice(TestFD, TestPath.c_str(), Buf,
40000, // Size
- 8000 // Offset
+ 80000 // Offset
);
EXPECT_FALSE(EC);
diff --git a/unittests/Support/Path.cpp b/unittests/Support/Path.cpp
index 6f5992b..0316241 100644
--- a/unittests/Support/Path.cpp
+++ b/unittests/Support/Path.cpp
@@ -141,6 +141,75 @@ TEST(Support, Path) {
}
}
+TEST(Support, RelativePathIterator) {
+ SmallString<64> Path(StringRef("c/d/e/foo.txt"));
+ typedef SmallVector<StringRef, 4> PathComponents;
+ PathComponents ExpectedPathComponents;
+ PathComponents ActualPathComponents;
+
+ StringRef(Path).split(ExpectedPathComponents, "/");
+
+ for (path::const_iterator I = path::begin(Path), E = path::end(Path); I != E;
+ ++I) {
+ ActualPathComponents.push_back(*I);
+ }
+
+ ASSERT_EQ(ExpectedPathComponents.size(), ActualPathComponents.size());
+
+ for (size_t i = 0; i <ExpectedPathComponents.size(); ++i) {
+ EXPECT_EQ(ExpectedPathComponents[i].str(), ActualPathComponents[i].str());
+ }
+}
+
+TEST(Support, AbsolutePathIterator) {
+ SmallString<64> Path(StringRef("/c/d/e/foo.txt"));
+ typedef SmallVector<StringRef, 4> PathComponents;
+ PathComponents ExpectedPathComponents;
+ PathComponents ActualPathComponents;
+
+ StringRef(Path).split(ExpectedPathComponents, "/");
+
+ // The root path will also be a component when iterating
+ ExpectedPathComponents[0] = "/";
+
+ for (path::const_iterator I = path::begin(Path), E = path::end(Path); I != E;
+ ++I) {
+ ActualPathComponents.push_back(*I);
+ }
+
+ ASSERT_EQ(ExpectedPathComponents.size(), ActualPathComponents.size());
+
+ for (size_t i = 0; i <ExpectedPathComponents.size(); ++i) {
+ EXPECT_EQ(ExpectedPathComponents[i].str(), ActualPathComponents[i].str());
+ }
+}
+
+#ifdef LLVM_ON_WIN32
+TEST(Support, AbsolutePathIteratorWin32) {
+ SmallString<64> Path(StringRef("c:\\c\\e\\foo.txt"));
+ typedef SmallVector<StringRef, 4> PathComponents;
+ PathComponents ExpectedPathComponents;
+ PathComponents ActualPathComponents;
+
+ StringRef(Path).split(ExpectedPathComponents, "\\");
+
+ // The root path (which comes after the drive name) will also be a component
+ // when iterating.
+ ExpectedPathComponents.insert(ExpectedPathComponents.begin()+1, "\\");
+
+ for (path::const_iterator I = path::begin(Path), E = path::end(Path); I != E;
+ ++I) {
+ ActualPathComponents.push_back(*I);
+ }
+
+ ASSERT_EQ(ExpectedPathComponents.size(), ActualPathComponents.size());
+
+ for (size_t i = 0; i <ExpectedPathComponents.size(); ++i) {
+ EXPECT_EQ(ExpectedPathComponents[i].str(), ActualPathComponents[i].str());
+ }
+}
+#endif // LLVM_ON_WIN32
+
class FileSystemTest : public testing::Test {
protected:
/// Unique temporary directory in which all created filesystem entities must
@@ -347,7 +416,25 @@ TEST_F(FileSystemTest, DirectoryIteration) {
ASSERT_LT(z0, za1);
}
-const char elf[] = {0x7f, 'E', 'L', 'F', 1, 2, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1};
+const char archive[] = "!<arch>\x0A";
+const char bitcode[] = "\xde\xc0\x17\x0b";
+const char coff_object[] = "\x00\x00......";
+const char coff_import_library[] = "\x00\x00\xff\xff....";
+const char elf_relocatable[] = { 0x7f, 'E', 'L', 'F', 1, 2, 1, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 1 };
+const char macho_universal_binary[] = "\xca\xfe\xba\xbe...\0x00";
+const char macho_object[] = "\xfe\xed\xfa\xce..........\x00\x01";
+const char macho_executable[] = "\xfe\xed\xfa\xce..........\x00\x02";
+const char macho_fixed_virtual_memory_shared_lib[] =
+ "\xfe\xed\xfa\xce..........\x00\x03";
+const char macho_core[] = "\xfe\xed\xfa\xce..........\x00\x04";
+const char macho_preload_executable[] = "\xfe\xed\xfa\xce..........\x00\x05";
+const char macho_dynamically_linked_shared_lib[] =
+ "\xfe\xed\xfa\xce..........\x00\x06";
+const char macho_dynamic_linker[] = "\xfe\xed\xfa\xce..........\x00\x07";
+const char macho_bundle[] = "\xfe\xed\xfa\xce..........\x00\x08";
+const char macho_dsym_companion[] = "\xfe\xed\xfa\xce..........\x00\x0a";
+const char windows_resource[] = "\x00\x00\x00\x00\x020\x00\x00\x00\xff";
TEST_F(FileSystemTest, Magic) {
struct type {
@@ -355,11 +442,27 @@ TEST_F(FileSystemTest, Magic) {
const char *magic_str;
size_t magic_str_len;
fs::file_magic magic;
- } types [] = {
- {"magic.archive", "!<arch>\x0A", 8, fs::file_magic::archive},
- {"magic.elf", elf, sizeof(elf),
- fs::file_magic::elf_relocatable}
- };
+ } types[] = {
+#define DEFINE(magic) \
+ { #magic, magic, sizeof(magic), fs::file_magic::magic }
+ DEFINE(archive),
+ DEFINE(bitcode),
+ DEFINE(coff_object),
+ DEFINE(coff_import_library),
+ DEFINE(elf_relocatable),
+ DEFINE(macho_universal_binary),
+ DEFINE(macho_object),
+ DEFINE(macho_executable),
+ DEFINE(macho_fixed_virtual_memory_shared_lib),
+ DEFINE(macho_core),
+ DEFINE(macho_preload_executable),
+ DEFINE(macho_dynamically_linked_shared_lib),
+ DEFINE(macho_dynamic_linker),
+ DEFINE(macho_bundle),
+ DEFINE(macho_dsym_companion),
+ DEFINE(windows_resource)
+#undef DEFINE
+ };
// Create some files filled with magic.
for (type *i = types, *e = types + (sizeof(types) / sizeof(type)); i != e;
@@ -392,7 +495,7 @@ TEST_F(FileSystemTest, CarriageReturn) {
}
{
OwningPtr<MemoryBuffer> Buf;
- MemoryBuffer::getFile(FilePathname, Buf);
+ MemoryBuffer::getFile(FilePathname.c_str(), Buf);
EXPECT_EQ(Buf->getBuffer(), "\r\n");
}
@@ -403,7 +506,7 @@ TEST_F(FileSystemTest, CarriageReturn) {
}
{
OwningPtr<MemoryBuffer> Buf;
- MemoryBuffer::getFile(FilePathname, Buf);
+ MemoryBuffer::getFile(FilePathname.c_str(), Buf);
EXPECT_EQ(Buf->getBuffer(), "\n");
}
}
@@ -431,7 +534,7 @@ TEST_F(FileSystemTest, FileMapping) {
mfr.data()[Val.size()] = 0;
// Unmap temp file
}
-
+
// Map it back in read-only
fs::mapped_file_region mfr(Twine(TempPath),
fs::mapped_file_region::readonly,
@@ -439,10 +542,10 @@ TEST_F(FileSystemTest, FileMapping) {
0,
EC);
ASSERT_NO_ERROR(EC);
-
+
// Verify content
EXPECT_EQ(StringRef(mfr.const_data()), Val);
-
+
// Unmap temp file
#if LLVM_HAS_RVALUE_REFERENCES
diff --git a/unittests/Support/ProcessTest.cpp b/unittests/Support/ProcessTest.cpp
index eff9c71..27c2318 100644
--- a/unittests/Support/ProcessTest.cpp
+++ b/unittests/Support/ProcessTest.cpp
@@ -39,4 +39,32 @@ TEST(ProcessTest, SelfProcess) {
EXPECT_GT(TimeValue::MaxTime, process::get_self()->get_wall_time());
}
+#ifdef _MSC_VER
+#define setenv(name, var, ignore) _putenv_s(name, var)
+#endif
+
+#if HAVE_SETENV || _MSC_VER
+TEST(ProcessTest, Basic) {
+ setenv("__LLVM_TEST_ENVIRON_VAR__", "abc", true);
+ Optional<std::string> val(Process::GetEnv("__LLVM_TEST_ENVIRON_VAR__"));
+ EXPECT_TRUE(val.hasValue());
+ EXPECT_STREQ("abc", val->c_str());
+}
+
+TEST(ProcessTest, None) {
+ Optional<std::string> val(
+ Process::GetEnv("__LLVM_TEST_ENVIRON_NO_SUCH_VAR__"));
+ EXPECT_FALSE(val.hasValue());
+}
+#endif
+
+#ifdef LLVM_ON_WIN32
+TEST(ProcessTest, Wchar) {
+ SetEnvironmentVariableW(L"__LLVM_TEST_ENVIRON_VAR__", L"abcdefghijklmnopqrs");
+ Optional<std::string> val(Process::GetEnv("__LLVM_TEST_ENVIRON_VAR__"));
+ EXPECT_TRUE(val.hasValue());
+ EXPECT_STREQ("abcdefghijklmnopqrs", val->c_str());
+}
+#endif
+
} // end anonymous namespace
diff --git a/unittests/Support/ProgramTest.cpp b/unittests/Support/ProgramTest.cpp
index 6852ca6..6eb990f 100644
--- a/unittests/Support/ProgramTest.cpp
+++ b/unittests/Support/ProgramTest.cpp
@@ -21,6 +21,20 @@
extern char **environ;
#endif
+#if defined(LLVM_ON_UNIX)
+#include <unistd.h>
+void sleep_for(unsigned int seconds) {
+ sleep(seconds);
+}
+#elif defined(LLVM_ON_WIN32)
+#include <windows.h>
+void sleep_for(unsigned int seconds) {
+ Sleep(seconds * 1000);
+}
+#else
+#error sleep_for is not implemented on your platform.
+#endif
+
// From TestMain.cpp.
extern const char *TestMainArgv0;
@@ -60,7 +74,7 @@ TEST(ProgramTest, CreateProcessTrailingSlash) {
sys::fs::getMainExecutable(TestMainArgv0, &ProgramTestStringArg1);
const char *argv[] = {
my_exe.c_str(),
- "--gtest_filter=ProgramTest.CreateProcessTrailingSlashChild",
+ "--gtest_filter=ProgramTest.CreateProcessTrailingSlash",
"-program-test-string-arg1", "has\\\\ trailing\\",
"-program-test-string-arg2", "has\\\\ trailing\\",
0
@@ -88,4 +102,93 @@ TEST(ProgramTest, CreateProcessTrailingSlash) {
EXPECT_EQ(0, rc);
}
+TEST(ProgramTest, TestExecuteNoWait) {
+ using namespace llvm::sys;
+
+ if (getenv("LLVM_PROGRAM_TEST_EXECUTE_NO_WAIT")) {
+ sleep_for(/*seconds*/ 1);
+ exit(0);
+ }
+
+ std::string Executable =
+ sys::fs::getMainExecutable(TestMainArgv0, &ProgramTestStringArg1);
+ const char *argv[] = {
+ Executable.c_str(),
+ "--gtest_filter=ProgramTest.TestExecuteNoWait",
+ 0
+ };
+
+ // Add LLVM_PROGRAM_TEST_EXECUTE_NO_WAIT to the environment of the child.
+ std::vector<const char *> envp;
+ CopyEnvironment(envp);
+ envp.push_back("LLVM_PROGRAM_TEST_EXECUTE_NO_WAIT=1");
+ envp.push_back(0);
+
+ std::string Error;
+ bool ExecutionFailed;
+ ProcessInfo PI1 =
+ ExecuteNoWait(Executable, argv, &envp[0], 0, 0, &Error, &ExecutionFailed);
+ ASSERT_FALSE(ExecutionFailed) << Error;
+ ASSERT_NE(PI1.Pid, 0) << "Invalid process id";
+
+ unsigned LoopCount = 0;
+
+ // Test that Wait() with WaitUntilTerminates=true works. In this case,
+ // LoopCount should only be incremented once.
+ while (true) {
+ ++LoopCount;
+ ProcessInfo WaitResult = Wait(PI1, 0, true, &Error);
+ ASSERT_TRUE(Error.empty());
+ if (WaitResult.Pid == PI1.Pid)
+ break;
+ }
+
+ EXPECT_EQ(LoopCount, 1u) << "LoopCount should be 1";
+
+ ProcessInfo PI2 =
+ ExecuteNoWait(Executable, argv, &envp[0], 0, 0, &Error, &ExecutionFailed);
+ ASSERT_FALSE(ExecutionFailed) << Error;
+ ASSERT_NE(PI2.Pid, 0) << "Invalid process id";
+
+ // Test that Wait() with SecondsToWait=0 performs a non-blocking wait. In this
+ // cse, LoopCount should be greater than 1 (more than one increment occurs).
+ while (true) {
+ ++LoopCount;
+ ProcessInfo WaitResult = Wait(PI2, 0, false, &Error);
+ ASSERT_TRUE(Error.empty());
+ if (WaitResult.Pid == PI2.Pid)
+ break;
+ }
+
+ ASSERT_GT(LoopCount, 1u) << "LoopCount should be >1";
+}
+
+TEST(ProgramTest, TestExecuteNegative) {
+ std::string Executable = "i_dont_exist";
+ const char *argv[] = { Executable.c_str(), 0 };
+
+ {
+ std::string Error;
+ bool ExecutionFailed;
+ int RetCode =
+ ExecuteAndWait(Executable, argv, 0, 0, 0, 0, &Error, &ExecutionFailed);
+ ASSERT_TRUE(RetCode < 0) << "On error ExecuteAndWait should return 0 or "
+ "positive value indicating the result code";
+ ASSERT_TRUE(ExecutionFailed);
+ ASSERT_FALSE(Error.empty());
+ }
+
+ {
+ std::string Error;
+ bool ExecutionFailed;
+ ProcessInfo PI =
+ ExecuteNoWait(Executable, argv, 0, 0, 0, &Error, &ExecutionFailed);
+ ASSERT_EQ(PI.Pid, 0)
+ << "On error ExecuteNoWait should return an invalid ProcessInfo";
+ ASSERT_TRUE(ExecutionFailed);
+ ASSERT_FALSE(Error.empty());
+ }
+
+}
+
} // end anonymous namespace
diff --git a/unittests/Support/RegexTest.cpp b/unittests/Support/RegexTest.cpp
index 02869b3..7b977f7 100644
--- a/unittests/Support/RegexTest.cpp
+++ b/unittests/Support/RegexTest.cpp
@@ -127,4 +127,12 @@ TEST_F(RegexTest, IsLiteralERE) {
EXPECT_FALSE(Regex::isLiteralERE("abc{1,2}"));
}
+TEST_F(RegexTest, IsValid) {
+ std::string Error;
+ EXPECT_FALSE(Regex("(foo").isValid(Error));
+ EXPECT_EQ("parentheses not balanced", Error);
+ EXPECT_FALSE(Regex("a[b-").isValid(Error));
+ EXPECT_EQ("invalid character range", Error);
+}
+
}
diff --git a/unittests/Support/SourceMgrTest.cpp b/unittests/Support/SourceMgrTest.cpp
new file mode 100644
index 0000000..2b69fe9
--- /dev/null
+++ b/unittests/Support/SourceMgrTest.cpp
@@ -0,0 +1,174 @@
+//===- unittests/Support/SourceMgrTest.cpp - SourceMgr tests --------------===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#include "llvm/Support/SourceMgr.h"
+#include "llvm/Support/MemoryBuffer.h"
+#include "llvm/Support/raw_ostream.h"
+#include "gtest/gtest.h"
+
+using namespace llvm;
+
+namespace {
+
+class SourceMgrTest : public testing::Test {
+public:
+ SourceMgr SM;
+ unsigned MainBufferID;
+ std::string Output;
+
+ void setMainBuffer(StringRef Text, StringRef BufferName) {
+ MemoryBuffer *MainBuffer = MemoryBuffer::getMemBuffer(Text, BufferName);
+ MainBufferID = SM.AddNewSourceBuffer(MainBuffer, llvm::SMLoc());
+ }
+
+ SMLoc getLoc(unsigned Offset) {
+ return SMLoc::getFromPointer(
+ SM.getMemoryBuffer(MainBufferID)->getBufferStart() + Offset);
+ }
+
+ SMRange getRange(unsigned Offset, unsigned Length) {
+ return SMRange(getLoc(Offset), getLoc(Offset + Length));
+ }
+
+ void printMessage(SMLoc Loc, SourceMgr::DiagKind Kind,
+ const Twine &Msg, ArrayRef<SMRange> Ranges,
+ ArrayRef<SMFixIt> FixIts) {
+ raw_string_ostream OS(Output);
+ SM.PrintMessage(OS, Loc, Kind, Msg, Ranges, FixIts);
+ }
+};
+
+} // unnamed namespace
+
+TEST_F(SourceMgrTest, BasicError) {
+ setMainBuffer("aaa bbb\nccc ddd\n", "file.in");
+ printMessage(getLoc(4), SourceMgr::DK_Error, "message", None, None);
+
+ EXPECT_EQ("file.in:1:5: error: message\n"
+ "aaa bbb\n"
+ " ^\n",
+ Output);
+}
+
+TEST_F(SourceMgrTest, BasicWarning) {
+ setMainBuffer("aaa bbb\nccc ddd\n", "file.in");
+ printMessage(getLoc(4), SourceMgr::DK_Warning, "message", None, None);
+
+ EXPECT_EQ("file.in:1:5: warning: message\n"
+ "aaa bbb\n"
+ " ^\n",
+ Output);
+}
+
+TEST_F(SourceMgrTest, BasicNote) {
+ setMainBuffer("aaa bbb\nccc ddd\n", "file.in");
+ printMessage(getLoc(4), SourceMgr::DK_Note, "message", None, None);
+
+ EXPECT_EQ("file.in:1:5: note: message\n"
+ "aaa bbb\n"
+ " ^\n",
+ Output);
+}
+
+TEST_F(SourceMgrTest, LocationAtEndOfLine) {
+ setMainBuffer("aaa bbb\nccc ddd\n", "file.in");
+ printMessage(getLoc(6), SourceMgr::DK_Error, "message", None, None);
+
+ EXPECT_EQ("file.in:1:7: error: message\n"
+ "aaa bbb\n"
+ " ^\n",
+ Output);
+}
+
+TEST_F(SourceMgrTest, LocationAtNewline) {
+ setMainBuffer("aaa bbb\nccc ddd\n", "file.in");
+ printMessage(getLoc(7), SourceMgr::DK_Error, "message", None, None);
+
+ EXPECT_EQ("file.in:1:8: error: message\n"
+ "aaa bbb\n"
+ " ^\n",
+ Output);
+}
+
+TEST_F(SourceMgrTest, BasicRange) {
+ setMainBuffer("aaa bbb\nccc ddd\n", "file.in");
+ printMessage(getLoc(4), SourceMgr::DK_Error, "message", getRange(4, 3), None);
+
+ EXPECT_EQ("file.in:1:5: error: message\n"
+ "aaa bbb\n"
+ " ^~~\n",
+ Output);
+}
+
+TEST_F(SourceMgrTest, RangeWithTab) {
+ setMainBuffer("aaa\tbbb\nccc ddd\n", "file.in");
+ printMessage(getLoc(4), SourceMgr::DK_Error, "message", getRange(3, 3), None);
+
+ EXPECT_EQ("file.in:1:5: error: message\n"
+ "aaa bbb\n"
+ " ~~~~~^~\n",
+ Output);
+}
+
+TEST_F(SourceMgrTest, MultiLineRange) {
+ setMainBuffer("aaa bbb\nccc ddd\n", "file.in");
+ printMessage(getLoc(4), SourceMgr::DK_Error, "message", getRange(4, 7), None);
+
+ EXPECT_EQ("file.in:1:5: error: message\n"
+ "aaa bbb\n"
+ " ^~~\n",
+ Output);
+}
+
+TEST_F(SourceMgrTest, MultipleRanges) {
+ setMainBuffer("aaa bbb\nccc ddd\n", "file.in");
+ SMRange Ranges[] = { getRange(0, 3), getRange(4, 3) };
+ printMessage(getLoc(4), SourceMgr::DK_Error, "message", Ranges, None);
+
+ EXPECT_EQ("file.in:1:5: error: message\n"
+ "aaa bbb\n"
+ "~~~ ^~~\n",
+ Output);
+}
+
+TEST_F(SourceMgrTest, OverlappingRanges) {
+ setMainBuffer("aaa bbb\nccc ddd\n", "file.in");
+ SMRange Ranges[] = { getRange(0, 3), getRange(2, 4) };
+ printMessage(getLoc(4), SourceMgr::DK_Error, "message", Ranges, None);
+
+ EXPECT_EQ("file.in:1:5: error: message\n"
+ "aaa bbb\n"
+ "~~~~^~\n",
+ Output);
+}
+
+TEST_F(SourceMgrTest, BasicFixit) {
+ setMainBuffer("aaa bbb\nccc ddd\n", "file.in");
+ printMessage(getLoc(4), SourceMgr::DK_Error, "message", None,
+ makeArrayRef(SMFixIt(getRange(4, 3), "zzz")));
+
+ EXPECT_EQ("file.in:1:5: error: message\n"
+ "aaa bbb\n"
+ " ^~~\n"
+ " zzz\n",
+ Output);
+}
+
+TEST_F(SourceMgrTest, FixitForTab) {
+ setMainBuffer("aaa\tbbb\nccc ddd\n", "file.in");
+ printMessage(getLoc(3), SourceMgr::DK_Error, "message", None,
+ makeArrayRef(SMFixIt(getRange(3, 1), "zzz")));
+
+ EXPECT_EQ("file.in:1:4: error: message\n"
+ "aaa bbb\n"
+ " ^^^^^\n"
+ " zzz\n",
+ Output);
+}
+
diff --git a/unittests/Support/ThreadLocalTest.cpp b/unittests/Support/ThreadLocalTest.cpp
new file mode 100644
index 0000000..dd4d706
--- /dev/null
+++ b/unittests/Support/ThreadLocalTest.cpp
@@ -0,0 +1,38 @@
+//===- llvm/unittest/Support/ThreadLocalTest.cpp - Therad Local tests ---===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#include "llvm/Support/ThreadLocal.h"
+#include "gtest/gtest.h"
+
+using namespace llvm;
+using namespace sys;
+
+namespace {
+
+class ThreadLocalTest : public ::testing::Test {
+};
+
+struct S {
+ int i;
+};
+
+TEST_F(ThreadLocalTest, Basics) {
+ ThreadLocal<const S> x;
+
+ EXPECT_EQ(0, x.get());
+
+ S s;
+ x.set(&s);
+ EXPECT_EQ(&s, x.get());
+
+ x.erase();
+ EXPECT_EQ(0, x.get());
+}
+
+}
diff --git a/unittests/Support/UnicodeTest.cpp b/unittests/Support/UnicodeTest.cpp
new file mode 100644
index 0000000..0733397
--- /dev/null
+++ b/unittests/Support/UnicodeTest.cpp
@@ -0,0 +1,93 @@
+//===- unittests/Support/UnicodeTest.cpp - Unicode.h tests ----------------===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#include "llvm/Support/Unicode.h"
+#include "gtest/gtest.h"
+
+namespace llvm {
+namespace sys {
+namespace unicode {
+namespace {
+
+TEST(Unicode, columnWidthUTF8) {
+ EXPECT_EQ(0, columnWidthUTF8(""));
+ EXPECT_EQ(1, columnWidthUTF8(" "));
+ EXPECT_EQ(1, columnWidthUTF8("a"));
+ EXPECT_EQ(1, columnWidthUTF8("~"));
+
+ EXPECT_EQ(6, columnWidthUTF8("abcdef"));
+
+ EXPECT_EQ(-1, columnWidthUTF8("\x01"));
+ EXPECT_EQ(-1, columnWidthUTF8("aaaaaaaaaa\x01"));
+ EXPECT_EQ(-1, columnWidthUTF8("\342\200\213")); // 200B ZERO WIDTH SPACE
+
+ // 00AD SOFT HYPHEN is displayed on most terminals as a space or a dash. Some
+ // text editors display it only when a line is broken at it, some use it as a
+ // line-break hint, but don't display. We choose terminal-oriented
+ // interpretation.
+ EXPECT_EQ(1, columnWidthUTF8("\302\255"));
+
+ EXPECT_EQ(0, columnWidthUTF8("\314\200")); // 0300 COMBINING GRAVE ACCENT
+ EXPECT_EQ(1, columnWidthUTF8("\340\270\201")); // 0E01 THAI CHARACTER KO KAI
+ EXPECT_EQ(2, columnWidthUTF8("\344\270\200")); // CJK UNIFIED IDEOGRAPH-4E00
+
+ EXPECT_EQ(4, columnWidthUTF8("\344\270\200\344\270\200"));
+ EXPECT_EQ(3, columnWidthUTF8("q\344\270\200"));
+ EXPECT_EQ(3, columnWidthUTF8("\314\200\340\270\201\344\270\200"));
+
+ // Invalid UTF-8 strings, columnWidthUTF8 should error out.
+ EXPECT_EQ(-2, columnWidthUTF8("\344"));
+ EXPECT_EQ(-2, columnWidthUTF8("\344\270"));
+ EXPECT_EQ(-2, columnWidthUTF8("\344\270\033"));
+ EXPECT_EQ(-2, columnWidthUTF8("\344\270\300"));
+ EXPECT_EQ(-2, columnWidthUTF8("\377\366\355"));
+
+ EXPECT_EQ(-2, columnWidthUTF8("qwer\344"));
+ EXPECT_EQ(-2, columnWidthUTF8("qwer\344\270"));
+ EXPECT_EQ(-2, columnWidthUTF8("qwer\344\270\033"));
+ EXPECT_EQ(-2, columnWidthUTF8("qwer\344\270\300"));
+ EXPECT_EQ(-2, columnWidthUTF8("qwer\377\366\355"));
+
+ // UTF-8 sequences longer than 4 bytes correspond to unallocated Unicode
+ // characters.
+ EXPECT_EQ(-2, columnWidthUTF8("\370\200\200\200\200")); // U+200000
+ EXPECT_EQ(-2, columnWidthUTF8("\374\200\200\200\200\200")); // U+4000000
+}
+
+TEST(Unicode, isPrintable) {
+ EXPECT_FALSE(isPrintable(0)); // <control-0000>-<control-001F>
+ EXPECT_FALSE(isPrintable(0x01));
+ EXPECT_FALSE(isPrintable(0x1F));
+ EXPECT_TRUE(isPrintable(' '));
+ EXPECT_TRUE(isPrintable('A'));
+ EXPECT_TRUE(isPrintable('~'));
+ EXPECT_FALSE(isPrintable(0x7F)); // <control-007F>..<control-009F>
+ EXPECT_FALSE(isPrintable(0x90));
+ EXPECT_FALSE(isPrintable(0x9F));
+
+ EXPECT_TRUE(isPrintable(0xAC));
+ EXPECT_TRUE(isPrintable(0xAD)); // SOFT HYPHEN is displayed on most terminals
+ // as either a space or a dash.
+ EXPECT_TRUE(isPrintable(0xAE));
+
+ EXPECT_TRUE(isPrintable(0x0377)); // GREEK SMALL LETTER PAMPHYLIAN DIGAMMA
+ EXPECT_FALSE(isPrintable(0x0378)); // <reserved-0378>..<reserved-0379>
+
+ EXPECT_FALSE(isPrintable(0x0600)); // ARABIC NUMBER SIGN
+
+ EXPECT_FALSE(isPrintable(0x1FFFF)); // <reserved-1F774>..<noncharacter-1FFFF>
+ EXPECT_TRUE(isPrintable(0x20000)); // CJK UNIFIED IDEOGRAPH-20000
+
+ EXPECT_FALSE(isPrintable(0x10FFFF)); // noncharacter
+}
+
+} // namespace
+} // namespace unicode
+} // namespace sys
+} // namespace llvm
diff --git a/unittests/Support/YAMLIOTest.cpp b/unittests/Support/YAMLIOTest.cpp
index 0993d8c..6c0b9e6 100644
--- a/unittests/Support/YAMLIOTest.cpp
+++ b/unittests/Support/YAMLIOTest.cpp
@@ -58,14 +58,24 @@ namespace yaml {
//
TEST(YAMLIO, TestMapRead) {
FooBar doc;
- Input yin("---\nfoo: 3\nbar: 5\n...\n");
- yin >> doc;
+ {
+ Input yin("---\nfoo: 3\nbar: 5\n...\n");
+ yin >> doc;
- EXPECT_FALSE(yin.error());
- EXPECT_EQ(doc.foo, 3);
- EXPECT_EQ(doc.bar,5);
-}
+ EXPECT_FALSE(yin.error());
+ EXPECT_EQ(doc.foo, 3);
+ EXPECT_EQ(doc.bar, 5);
+ }
+ {
+ Input yin("{foo: 3, bar: 5}");
+ yin >> doc;
+
+ EXPECT_FALSE(yin.error());
+ EXPECT_EQ(doc.foo, 3);
+ EXPECT_EQ(doc.bar, 5);
+ }
+}
//
// Test the reading of a yaml sequence of mappings
@@ -273,7 +283,64 @@ TEST(YAMLIO, TestReadWriteBuiltInTypes) {
}
}
+struct StringTypes {
+ llvm::StringRef str1;
+ llvm::StringRef str2;
+ llvm::StringRef str3;
+ llvm::StringRef str4;
+ llvm::StringRef str5;
+};
+
+namespace llvm {
+namespace yaml {
+ template <>
+ struct MappingTraits<StringTypes> {
+ static void mapping(IO &io, StringTypes& st) {
+ io.mapRequired("str1", st.str1);
+ io.mapRequired("str2", st.str2);
+ io.mapRequired("str3", st.str3);
+ io.mapRequired("str4", st.str4);
+ io.mapRequired("str5", st.str5);
+ }
+ };
+}
+}
+
+TEST(YAMLIO, TestReadWriteStringTypes) {
+ std::string intermediate;
+ {
+ StringTypes map;
+ map.str1 = "'aaa";
+ map.str2 = "\"bbb";
+ map.str3 = "`ccc";
+ map.str4 = "@ddd";
+ map.str5 = "";
+
+ llvm::raw_string_ostream ostr(intermediate);
+ Output yout(ostr);
+ yout << map;
+ }
+ llvm::StringRef flowOut(intermediate);
+ EXPECT_NE(llvm::StringRef::npos, flowOut.find("'''aaa"));
+ EXPECT_NE(llvm::StringRef::npos, flowOut.find("'\"bbb'"));
+ EXPECT_NE(llvm::StringRef::npos, flowOut.find("'`ccc'"));
+ EXPECT_NE(llvm::StringRef::npos, flowOut.find("'@ddd'"));
+ EXPECT_NE(llvm::StringRef::npos, flowOut.find("''\n"));
+
+ {
+ Input yin(intermediate);
+ StringTypes map;
+ yin >> map;
+
+ EXPECT_FALSE(yin.error());
+ EXPECT_TRUE(map.str1.equals("'aaa"));
+ EXPECT_TRUE(map.str2.equals("\"bbb"));
+ EXPECT_TRUE(map.str3.equals("`ccc"));
+ EXPECT_TRUE(map.str4.equals("@ddd"));
+ EXPECT_TRUE(map.str5.equals(""));
+ }
+}
//===----------------------------------------------------------------------===//
// Test ScalarEnumerationTraits
@@ -600,9 +667,9 @@ TEST(YAMLIO, TestReadWriteMyFlowSequence) {
map.numbers.push_back(1024);
llvm::raw_string_ostream ostr(intermediate);
- Output yout(ostr);
+ Output yout(ostr);
yout << map;
-
+
// Verify sequences were written in flow style
ostr.flush();
llvm::StringRef flowOut(intermediate);
@@ -932,6 +999,161 @@ TEST(YAMLIO, TestSequenceDocListWriteAndRead) {
}
}
+//===----------------------------------------------------------------------===//
+// Test document tags
+//===----------------------------------------------------------------------===//
+
+struct MyDouble {
+ MyDouble() : value(0.0) { }
+ MyDouble(double x) : value(x) { }
+ double value;
+};
+
+LLVM_YAML_IS_DOCUMENT_LIST_VECTOR(MyDouble)
+
+
+namespace llvm {
+namespace yaml {
+ template <>
+ struct MappingTraits<MyDouble> {
+ static void mapping(IO &io, MyDouble &d) {
+ if (io.mapTag("!decimal", true)) {
+ mappingDecimal(io, d);
+ } else if (io.mapTag("!fraction")) {
+ mappingFraction(io, d);
+ }
+ }
+ static void mappingDecimal(IO &io, MyDouble &d) {
+ io.mapRequired("value", d.value);
+ }
+ static void mappingFraction(IO &io, MyDouble &d) {
+ double num, denom;
+ io.mapRequired("numerator", num);
+ io.mapRequired("denominator", denom);
+ // convert fraction to double
+ d.value = num/denom;
+ }
+ };
+ }
+}
+
+
+//
+// Test the reading of two different tagged yaml documents.
+//
+TEST(YAMLIO, TestTaggedDocuments) {
+ std::vector<MyDouble> docList;
+ Input yin("--- !decimal\nvalue: 3.0\n"
+ "--- !fraction\nnumerator: 9.0\ndenominator: 2\n...\n");
+ yin >> docList;
+ EXPECT_FALSE(yin.error());
+ EXPECT_EQ(docList.size(), 2UL);
+ EXPECT_EQ(docList[0].value, 3.0);
+ EXPECT_EQ(docList[1].value, 4.5);
+}
+
+
+
+//
+// Test writing then reading back tagged documents
+//
+TEST(YAMLIO, TestTaggedDocumentsWriteAndRead) {
+ std::string intermediate;
+ {
+ MyDouble a(10.25);
+ MyDouble b(-3.75);
+ std::vector<MyDouble> docList;
+ docList.push_back(a);
+ docList.push_back(b);
+
+ llvm::raw_string_ostream ostr(intermediate);
+ Output yout(ostr);
+ yout << docList;
+ }
+
+ {
+ Input yin(intermediate);
+ std::vector<MyDouble> docList2;
+ yin >> docList2;
+
+ EXPECT_FALSE(yin.error());
+ EXPECT_EQ(docList2.size(), 2UL);
+ EXPECT_EQ(docList2[0].value, 10.25);
+ EXPECT_EQ(docList2[1].value, -3.75);
+ }
+}
+
+
+//===----------------------------------------------------------------------===//
+// Test dyn_cast<> on IO object
+//===----------------------------------------------------------------------===//
+
+struct DynCast {
+ int value;
+};
+typedef std::vector<DynCast> DynCastSequence;
+
+LLVM_YAML_IS_SEQUENCE_VECTOR(DynCast)
+
+namespace llvm {
+namespace yaml {
+ template <>
+ struct MappingTraits<DynCast> {
+ static void mapping(IO &io, DynCast& info) {
+ // Change 10 to 13 when writing yaml.
+ if (Output *output = dyn_cast<Output>(&io)) {
+ (void)output;
+ if (info.value == 10)
+ info.value = 13;
+ }
+ io.mapRequired("value", info.value);
+ // Change 20 to 23 when parsing yaml.
+ if (Input *input = dyn_cast<Input>(&io)) {
+ (void)input;
+ if (info.value == 20)
+ info.value = 23;
+ }
+ }
+ };
+}
+}
+
+//
+// Test writing then reading back a sequence of mappings
+//
+TEST(YAMLIO, TestDynCast) {
+ std::string intermediate;
+ {
+ DynCast entry1;
+ entry1.value = 10;
+ DynCast entry2;
+ entry2.value = 20;
+ DynCast entry3;
+ entry3.value = 30;
+ DynCastSequence seq;
+ seq.push_back(entry1);
+ seq.push_back(entry2);
+ seq.push_back(entry3);
+
+ llvm::raw_string_ostream ostr(intermediate);
+ Output yout(ostr);
+ yout << seq;
+ }
+
+ {
+ Input yin(intermediate);
+ DynCastSequence seq2;
+ yin >> seq2;
+
+ EXPECT_FALSE(yin.error());
+ EXPECT_EQ(seq2.size(), 3UL);
+ EXPECT_EQ(seq2[0].value, 13); // Verify changed to 13.
+ EXPECT_EQ(seq2[1].value, 23); // Verify changed to 23.
+ EXPECT_EQ(seq2[2].value, 30); // Verify stays same.
+ }
+}
+
+
//===----------------------------------------------------------------------===//
// Test error handling
@@ -952,8 +1174,9 @@ TEST(YAMLIO, TestColorsReadError) {
"c1: blue\n"
"c2: purple\n"
"c3: green\n"
- "...\n");
- yin.setDiagHandler(suppressErrorMessages);
+ "...\n",
+ /*Ctxt=*/NULL,
+ suppressErrorMessages);
yin >> map;
EXPECT_TRUE(yin.error());
}
@@ -968,8 +1191,9 @@ TEST(YAMLIO, TestFlagsReadError) {
"f1: [ big ]\n"
"f2: [ round, hollow ]\n"
"f3: []\n"
- "...\n");
- yin.setDiagHandler(suppressErrorMessages);
+ "...\n",
+ /*Ctxt=*/NULL,
+ suppressErrorMessages);
yin >> map;
EXPECT_TRUE(yin.error());
@@ -986,8 +1210,9 @@ TEST(YAMLIO, TestReadBuiltInTypesUint8Error) {
"- 255\n"
"- 0\n"
"- 257\n"
- "...\n");
- yin.setDiagHandler(suppressErrorMessages);
+ "...\n",
+ /*Ctxt=*/NULL,
+ suppressErrorMessages);
yin >> seq;
EXPECT_TRUE(yin.error());
@@ -1004,8 +1229,9 @@ TEST(YAMLIO, TestReadBuiltInTypesUint16Error) {
"- 65535\n"
"- 0\n"
"- 66000\n"
- "...\n");
- yin.setDiagHandler(suppressErrorMessages);
+ "...\n",
+ /*Ctxt=*/NULL,
+ suppressErrorMessages);
yin >> seq;
EXPECT_TRUE(yin.error());
@@ -1022,8 +1248,9 @@ TEST(YAMLIO, TestReadBuiltInTypesUint32Error) {
"- 4000000000\n"
"- 0\n"
"- 5000000000\n"
- "...\n");
- yin.setDiagHandler(suppressErrorMessages);
+ "...\n",
+ /*Ctxt=*/NULL,
+ suppressErrorMessages);
yin >> seq;
EXPECT_TRUE(yin.error());
@@ -1040,8 +1267,9 @@ TEST(YAMLIO, TestReadBuiltInTypesUint64Error) {
"- 18446744073709551615\n"
"- 0\n"
"- 19446744073709551615\n"
- "...\n");
- yin.setDiagHandler(suppressErrorMessages);
+ "...\n",
+ /*Ctxt=*/NULL,
+ suppressErrorMessages);
yin >> seq;
EXPECT_TRUE(yin.error());
@@ -1059,8 +1287,9 @@ TEST(YAMLIO, TestReadBuiltInTypesint8OverError) {
"- 0\n"
"- 127\n"
"- 128\n"
- "...\n");
- yin.setDiagHandler(suppressErrorMessages);
+ "...\n",
+ /*Ctxt=*/NULL,
+ suppressErrorMessages);
yin >> seq;
EXPECT_TRUE(yin.error());
@@ -1076,8 +1305,9 @@ TEST(YAMLIO, TestReadBuiltInTypesint8UnderError) {
"- 0\n"
"- 127\n"
"- -129\n"
- "...\n");
- yin.setDiagHandler(suppressErrorMessages);
+ "...\n",
+ /*Ctxt=*/NULL,
+ suppressErrorMessages);
yin >> seq;
EXPECT_TRUE(yin.error());
@@ -1095,8 +1325,9 @@ TEST(YAMLIO, TestReadBuiltInTypesint16UnderError) {
"- 0\n"
"- -32768\n"
"- -32769\n"
- "...\n");
- yin.setDiagHandler(suppressErrorMessages);
+ "...\n",
+ /*Ctxt=*/NULL,
+ suppressErrorMessages);
yin >> seq;
EXPECT_TRUE(yin.error());
@@ -1113,8 +1344,9 @@ TEST(YAMLIO, TestReadBuiltInTypesint16OverError) {
"- 0\n"
"- -32768\n"
"- 32768\n"
- "...\n");
- yin.setDiagHandler(suppressErrorMessages);
+ "...\n",
+ /*Ctxt=*/NULL,
+ suppressErrorMessages);
yin >> seq;
EXPECT_TRUE(yin.error());
@@ -1132,8 +1364,9 @@ TEST(YAMLIO, TestReadBuiltInTypesint32UnderError) {
"- 0\n"
"- -2147483648\n"
"- -2147483649\n"
- "...\n");
- yin.setDiagHandler(suppressErrorMessages);
+ "...\n",
+ /*Ctxt=*/NULL,
+ suppressErrorMessages);
yin >> seq;
EXPECT_TRUE(yin.error());
@@ -1149,8 +1382,9 @@ TEST(YAMLIO, TestReadBuiltInTypesint32OverError) {
"- 0\n"
"- -2147483648\n"
"- 2147483649\n"
- "...\n");
- yin.setDiagHandler(suppressErrorMessages);
+ "...\n",
+ /*Ctxt=*/NULL,
+ suppressErrorMessages);
yin >> seq;
EXPECT_TRUE(yin.error());
@@ -1168,8 +1402,9 @@ TEST(YAMLIO, TestReadBuiltInTypesint64UnderError) {
"- 0\n"
"- 9223372036854775807\n"
"- -9223372036854775809\n"
- "...\n");
- yin.setDiagHandler(suppressErrorMessages);
+ "...\n",
+ /*Ctxt=*/NULL,
+ suppressErrorMessages);
yin >> seq;
EXPECT_TRUE(yin.error());
@@ -1185,8 +1420,9 @@ TEST(YAMLIO, TestReadBuiltInTypesint64OverError) {
"- 0\n"
"- 9223372036854775807\n"
"- 9223372036854775809\n"
- "...\n");
- yin.setDiagHandler(suppressErrorMessages);
+ "...\n",
+ /*Ctxt=*/NULL,
+ suppressErrorMessages);
yin >> seq;
EXPECT_TRUE(yin.error());
@@ -1203,8 +1439,9 @@ TEST(YAMLIO, TestReadBuiltInTypesFloatError) {
"- 1000.1\n"
"- -123.456\n"
"- 1.2.3\n"
- "...\n");
- yin.setDiagHandler(suppressErrorMessages);
+ "...\n",
+ /*Ctxt=*/NULL,
+ suppressErrorMessages);
yin >> seq;
EXPECT_TRUE(yin.error());
@@ -1221,8 +1458,9 @@ TEST(YAMLIO, TestReadBuiltInTypesDoubleError) {
"- 1000.1\n"
"- -123.456\n"
"- 1.2.3\n"
- "...\n");
- yin.setDiagHandler(suppressErrorMessages);
+ "...\n",
+ /*Ctxt=*/NULL,
+ suppressErrorMessages);
yin >> seq;
EXPECT_TRUE(yin.error());
@@ -1238,8 +1476,9 @@ TEST(YAMLIO, TestReadBuiltInTypesHex8Error) {
"- 0x12\n"
"- 0xFE\n"
"- 0x123\n"
- "...\n");
- yin.setDiagHandler(suppressErrorMessages);
+ "...\n",
+ /*Ctxt=*/NULL,
+ suppressErrorMessages);
yin >> seq;
EXPECT_TRUE(yin.error());
@@ -1256,8 +1495,9 @@ TEST(YAMLIO, TestReadBuiltInTypesHex16Error) {
"- 0x0012\n"
"- 0xFEFF\n"
"- 0x12345\n"
- "...\n");
- yin.setDiagHandler(suppressErrorMessages);
+ "...\n",
+ /*Ctxt=*/NULL,
+ suppressErrorMessages);
yin >> seq;
EXPECT_TRUE(yin.error());
@@ -1273,8 +1513,9 @@ TEST(YAMLIO, TestReadBuiltInTypesHex32Error) {
"- 0x0012\n"
"- 0xFEFF0000\n"
"- 0x1234556789\n"
- "...\n");
- yin.setDiagHandler(suppressErrorMessages);
+ "...\n",
+ /*Ctxt=*/NULL,
+ suppressErrorMessages);
yin >> seq;
EXPECT_TRUE(yin.error());
@@ -1290,10 +1531,114 @@ TEST(YAMLIO, TestReadBuiltInTypesHex64Error) {
"- 0x0012\n"
"- 0xFFEEDDCCBBAA9988\n"
"- 0x12345567890ABCDEF0\n"
- "...\n");
- yin.setDiagHandler(suppressErrorMessages);
+ "...\n",
+ /*Ctxt=*/NULL,
+ suppressErrorMessages);
yin >> seq;
EXPECT_TRUE(yin.error());
}
+TEST(YAMLIO, TestMalformedMapFailsGracefully) {
+ FooBar doc;
+ {
+ // We pass the suppressErrorMessages handler to handle the error
+ // message generated in the constructor of Input.
+ Input yin("{foo:3, bar: 5}", /*Ctxt=*/NULL, suppressErrorMessages);
+ yin >> doc;
+ EXPECT_TRUE(yin.error());
+ }
+
+ {
+ Input yin("---\nfoo:3\nbar: 5\n...\n", /*Ctxt=*/NULL, suppressErrorMessages);
+ yin >> doc;
+ EXPECT_TRUE(yin.error());
+ }
+}
+
+struct OptionalTest {
+ std::vector<int> Numbers;
+};
+
+struct OptionalTestSeq {
+ std::vector<OptionalTest> Tests;
+};
+
+LLVM_YAML_IS_SEQUENCE_VECTOR(OptionalTest)
+namespace llvm {
+namespace yaml {
+ template <>
+ struct MappingTraits<OptionalTest> {
+ static void mapping(IO& IO, OptionalTest &OT) {
+ IO.mapOptional("Numbers", OT.Numbers);
+ }
+ };
+
+ template <>
+ struct MappingTraits<OptionalTestSeq> {
+ static void mapping(IO &IO, OptionalTestSeq &OTS) {
+ IO.mapOptional("Tests", OTS.Tests);
+ }
+ };
+}
+}
+
+TEST(YAMLIO, SequenceElideTest) {
+ // Test that writing out a purely optional structure with its fields set to
+ // default followed by other data is properly read back in.
+ OptionalTestSeq Seq;
+ OptionalTest One, Two, Three, Four;
+ int N[] = {1, 2, 3};
+ Three.Numbers.assign(N, N + 3);
+ Seq.Tests.push_back(One);
+ Seq.Tests.push_back(Two);
+ Seq.Tests.push_back(Three);
+ Seq.Tests.push_back(Four);
+
+ std::string intermediate;
+ {
+ llvm::raw_string_ostream ostr(intermediate);
+ Output yout(ostr);
+ yout << Seq;
+ }
+
+ Input yin(intermediate);
+ OptionalTestSeq Seq2;
+ yin >> Seq2;
+
+ EXPECT_FALSE(yin.error());
+
+ EXPECT_EQ(4UL, Seq2.Tests.size());
+
+ EXPECT_TRUE(Seq2.Tests[0].Numbers.empty());
+ EXPECT_TRUE(Seq2.Tests[1].Numbers.empty());
+
+ EXPECT_EQ(1, Seq2.Tests[2].Numbers[0]);
+ EXPECT_EQ(2, Seq2.Tests[2].Numbers[1]);
+ EXPECT_EQ(3, Seq2.Tests[2].Numbers[2]);
+
+ EXPECT_TRUE(Seq2.Tests[3].Numbers.empty());
+}
+
+TEST(YAMLIO, TestEmptyStringFailsForMapWithRequiredFields) {
+ FooBar doc;
+ Input yin("");
+ yin >> doc;
+ EXPECT_TRUE(yin.error());
+}
+
+TEST(YAMLIO, TestEmptyStringSucceedsForMapWithOptionalFields) {
+ OptionalTest doc;
+ Input yin("");
+ yin >> doc;
+ EXPECT_FALSE(yin.error());
+}
+
+TEST(YAMLIO, TestEmptyStringSucceedsForSequence) {
+ std::vector<uint8_t> seq;
+ Input yin("", /*Ctxt=*/NULL, suppressErrorMessages);
+ yin >> seq;
+
+ EXPECT_FALSE(yin.error());
+ EXPECT_TRUE(seq.empty());
+}
diff --git a/unittests/Transforms/Utils/SpecialCaseList.cpp b/unittests/Transforms/Utils/SpecialCaseList.cpp
index 9deee3c..07ac908 100644
--- a/unittests/Transforms/Utils/SpecialCaseList.cpp
+++ b/unittests/Transforms/Utils/SpecialCaseList.cpp
@@ -34,9 +34,22 @@ protected:
M, ST, false, GlobalValue::ExternalLinkage, 0, Name);
}
- SpecialCaseList *makeSpecialCaseList(StringRef List) {
+ GlobalAlias *makeAlias(StringRef Name, GlobalValue *Aliasee) {
+ return new GlobalAlias(Aliasee->getType(), GlobalValue::ExternalLinkage,
+ Name, Aliasee, Aliasee->getParent());
+ }
+
+ SpecialCaseList *makeSpecialCaseList(StringRef List, std::string &Error) {
OwningPtr<MemoryBuffer> MB(MemoryBuffer::getMemBuffer(List));
- return new SpecialCaseList(MB.get());
+ return SpecialCaseList::create(MB.get(), Error);
+ }
+
+ SpecialCaseList *makeSpecialCaseList(StringRef List) {
+ std::string Error;
+ SpecialCaseList *SCL = makeSpecialCaseList(List, Error);
+ assert(SCL);
+ assert(Error == "");
+ return SCL;
}
LLVMContext Ctx;
@@ -86,8 +99,6 @@ TEST_F(SpecialCaseListTest, FunctionIsIn) {
SCL.reset(makeSpecialCaseList("fun:foo=functional\n"));
EXPECT_TRUE(SCL->isIn(*Foo, "functional"));
StringRef Category;
- EXPECT_TRUE(SCL->findCategory(*Foo, Category));
- EXPECT_EQ("functional", Category);
EXPECT_FALSE(SCL->isIn(*Bar, "functional"));
}
@@ -139,10 +150,48 @@ TEST_F(SpecialCaseListTest, GlobalIsIn) {
EXPECT_TRUE(SCL->isIn(*Bar, "init"));
}
+TEST_F(SpecialCaseListTest, AliasIsIn) {
+ Module M("hello", Ctx);
+ Function *Foo = makeFunction("foo", M);
+ GlobalVariable *Bar = makeGlobal("bar", "t", M);
+ GlobalAlias *FooAlias = makeAlias("fooalias", Foo);
+ GlobalAlias *BarAlias = makeAlias("baralias", Bar);
+
+ OwningPtr<SpecialCaseList> SCL(makeSpecialCaseList("fun:foo\n"));
+ EXPECT_FALSE(SCL->isIn(*FooAlias));
+ EXPECT_FALSE(SCL->isIn(*BarAlias));
+
+ SCL.reset(makeSpecialCaseList("global:bar\n"));
+ EXPECT_FALSE(SCL->isIn(*FooAlias));
+ EXPECT_FALSE(SCL->isIn(*BarAlias));
+
+ SCL.reset(makeSpecialCaseList("global:fooalias\n"));
+ EXPECT_FALSE(SCL->isIn(*FooAlias));
+ EXPECT_FALSE(SCL->isIn(*BarAlias));
+
+ SCL.reset(makeSpecialCaseList("fun:fooalias\n"));
+ EXPECT_TRUE(SCL->isIn(*FooAlias));
+ EXPECT_FALSE(SCL->isIn(*BarAlias));
+
+ SCL.reset(makeSpecialCaseList("global:baralias=init\n"));
+ EXPECT_FALSE(SCL->isIn(*FooAlias, "init"));
+ EXPECT_TRUE(SCL->isIn(*BarAlias, "init"));
+
+ SCL.reset(makeSpecialCaseList("type:t=init\n"));
+ EXPECT_FALSE(SCL->isIn(*FooAlias, "init"));
+ EXPECT_TRUE(SCL->isIn(*BarAlias, "init"));
+
+ SCL.reset(makeSpecialCaseList("fun:baralias=init\n"));
+ EXPECT_FALSE(SCL->isIn(*FooAlias, "init"));
+ EXPECT_FALSE(SCL->isIn(*BarAlias, "init"));
+}
+
TEST_F(SpecialCaseListTest, Substring) {
Module M("othello", Ctx);
Function *F = makeFunction("tomfoolery", M);
GlobalVariable *GV = makeGlobal("bartender", "t", M);
+ GlobalAlias *GA1 = makeAlias("buffoonery", F);
+ GlobalAlias *GA2 = makeAlias("foobar", GV);
OwningPtr<SpecialCaseList> SCL(makeSpecialCaseList("src:hello\n"
"fun:foo\n"
@@ -150,9 +199,34 @@ TEST_F(SpecialCaseListTest, Substring) {
EXPECT_FALSE(SCL->isIn(M));
EXPECT_FALSE(SCL->isIn(*F));
EXPECT_FALSE(SCL->isIn(*GV));
+ EXPECT_FALSE(SCL->isIn(*GA1));
+ EXPECT_FALSE(SCL->isIn(*GA2));
SCL.reset(makeSpecialCaseList("fun:*foo*\n"));
EXPECT_TRUE(SCL->isIn(*F));
+ EXPECT_TRUE(SCL->isIn(*GA1));
+}
+
+TEST_F(SpecialCaseListTest, InvalidSpecialCaseList) {
+ std::string Error;
+ EXPECT_EQ(0, makeSpecialCaseList("badline", Error));
+ EXPECT_EQ("Malformed line 1: 'badline'", Error);
+ EXPECT_EQ(0, makeSpecialCaseList("src:bad[a-", Error));
+ EXPECT_EQ("Malformed regex in line 1: 'bad[a-': invalid character range",
+ Error);
+ EXPECT_EQ(0, makeSpecialCaseList("src:a.c\n"
+ "fun:fun(a\n",
+ Error));
+ EXPECT_EQ("Malformed regex in line 2: 'fun(a': parentheses not balanced",
+ Error);
+ EXPECT_EQ(0, SpecialCaseList::create("unexisting", Error));
+ EXPECT_EQ(0U, Error.find("Can't open file 'unexisting':"));
+}
+
+TEST_F(SpecialCaseListTest, EmptySpecialCaseList) {
+ OwningPtr<SpecialCaseList> SCL(makeSpecialCaseList(""));
+ Module M("foo", Ctx);
+ EXPECT_FALSE(SCL->isIn(M));
}
}