summaryrefslogtreecommitdiff
path: root/unittests
diff options
context:
space:
mode:
Diffstat (limited to 'unittests')
-rw-r--r--unittests/Analysis/ScalarEvolutionTest.cpp88
-rw-r--r--unittests/DebugInfo/CodeView/CMakeLists.txt1
-rw-r--r--unittests/DebugInfo/CodeView/ErrorChecking.h9
-rw-r--r--unittests/DebugInfo/CodeView/TypeIndexDiscoveryTest.cpp496
-rw-r--r--unittests/DebugInfo/DWARF/DWARFDebugInfoTest.cpp24
-rw-r--r--unittests/DebugInfo/PDB/MappedBlockStreamTest.cpp51
-rw-r--r--unittests/IR/BasicBlockTest.cpp75
-rw-r--r--unittests/IR/CMakeLists.txt1
-rw-r--r--unittests/IR/DominatorTreeTest.cpp129
-rw-r--r--unittests/Support/CrashRecoveryTest.cpp4
10 files changed, 763 insertions, 115 deletions
diff --git a/unittests/Analysis/ScalarEvolutionTest.cpp b/unittests/Analysis/ScalarEvolutionTest.cpp
index b21f4dc622bb..fcbbb46f7a7e 100644
--- a/unittests/Analysis/ScalarEvolutionTest.cpp
+++ b/unittests/Analysis/ScalarEvolutionTest.cpp
@@ -7,21 +7,22 @@
//
//===----------------------------------------------------------------------===//
-#include "llvm/Analysis/ScalarEvolutionExpander.h"
-#include "llvm/Analysis/ScalarEvolutionExpressions.h"
+#include "llvm/ADT/SmallVector.h"
#include "llvm/Analysis/AssumptionCache.h"
#include "llvm/Analysis/LoopInfo.h"
-#include "llvm/Analysis/TargetLibraryInfo.h"
-#include "llvm/ADT/SmallVector.h"
#include "llvm/Analysis/LoopInfo.h"
+#include "llvm/Analysis/ScalarEvolutionExpander.h"
+#include "llvm/Analysis/ScalarEvolutionExpressions.h"
+#include "llvm/Analysis/TargetLibraryInfo.h"
#include "llvm/AsmParser/Parser.h"
#include "llvm/IR/Constants.h"
#include "llvm/IR/Dominators.h"
#include "llvm/IR/GlobalVariable.h"
+#include "llvm/IR/IRBuilder.h"
#include "llvm/IR/InstIterator.h"
#include "llvm/IR/LLVMContext.h"
-#include "llvm/IR/Module.h"
#include "llvm/IR/LegacyPassManager.h"
+#include "llvm/IR/Module.h"
#include "llvm/IR/Verifier.h"
#include "llvm/Support/SourceMgr.h"
#include "gtest/gtest.h"
@@ -853,5 +854,82 @@ TEST_F(ScalarEvolutionsTest, SCEVZeroExtendExpr) {
Type *I128Ty = Type::getInt128Ty(Context);
SE.getZeroExtendExpr(S, I128Ty);
}
+
+// Make sure that SCEV doesn't introduce illegal ptrtoint/inttoptr instructions
+TEST_F(ScalarEvolutionsTest, SCEVZeroExtendExprNonIntegral) {
+ /*
+ * Create the following code:
+ * func(i64 addrspace(10)* %arg)
+ * top:
+ * br label %L.ph
+ * L.ph:
+ * br label %L
+ * L:
+ * %phi = phi i64 [i64 0, %L.ph], [ %add, %L2 ]
+ * %add = add i64 %phi2, 1
+ * br i1 undef, label %post, label %L2
+ * post:
+ * %gepbase = getelementptr i64 addrspace(10)* %arg, i64 1
+ * #= %gep = getelementptr i64 addrspace(10)* %gepbase, i64 %add =#
+ * ret void
+ *
+ * We will create the appropriate SCEV expression for %gep and expand it,
+ * then check that no inttoptr/ptrtoint instructions got inserted.
+ */
+
+ // Create a module with non-integral pointers in it's datalayout
+ Module NIM("nonintegral", Context);
+ std::string DataLayout = M.getDataLayoutStr();
+ if (!DataLayout.empty())
+ DataLayout += "-";
+ DataLayout += "ni:10";
+ NIM.setDataLayout(DataLayout);
+
+ Type *T_int1 = Type::getInt1Ty(Context);
+ Type *T_int64 = Type::getInt64Ty(Context);
+ Type *T_pint64 = T_int64->getPointerTo(10);
+
+ FunctionType *FTy =
+ FunctionType::get(Type::getVoidTy(Context), {T_pint64}, false);
+ Function *F = cast<Function>(NIM.getOrInsertFunction("foo", FTy));
+
+ Argument *Arg = &*F->arg_begin();
+
+ BasicBlock *Top = BasicBlock::Create(Context, "top", F);
+ BasicBlock *LPh = BasicBlock::Create(Context, "L.ph", F);
+ BasicBlock *L = BasicBlock::Create(Context, "L", F);
+ BasicBlock *Post = BasicBlock::Create(Context, "post", F);
+
+ IRBuilder<> Builder(Top);
+ Builder.CreateBr(LPh);
+
+ Builder.SetInsertPoint(LPh);
+ Builder.CreateBr(L);
+
+ Builder.SetInsertPoint(L);
+ PHINode *Phi = Builder.CreatePHI(T_int64, 2);
+ Value *Add = Builder.CreateAdd(Phi, ConstantInt::get(T_int64, 1), "add");
+ Builder.CreateCondBr(UndefValue::get(T_int1), L, Post);
+ Phi->addIncoming(ConstantInt::get(T_int64, 0), LPh);
+ Phi->addIncoming(Add, L);
+
+ Builder.SetInsertPoint(Post);
+ Value *GepBase = Builder.CreateGEP(Arg, ConstantInt::get(T_int64, 1));
+ Instruction *Ret = Builder.CreateRetVoid();
+
+ ScalarEvolution SE = buildSE(*F);
+ auto *AddRec =
+ SE.getAddRecExpr(SE.getUnknown(GepBase), SE.getConstant(T_int64, 1),
+ LI->getLoopFor(L), SCEV::FlagNUW);
+
+ SCEVExpander Exp(SE, NIM.getDataLayout(), "expander");
+ Exp.disableCanonicalMode();
+ Exp.expandCodeFor(AddRec, T_pint64, Ret);
+
+ // Make sure none of the instructions inserted were inttoptr/ptrtoint.
+ // The verifier will check this.
+ EXPECT_FALSE(verifyFunction(*F, &errs()));
+}
+
} // end anonymous namespace
} // end namespace llvm
diff --git a/unittests/DebugInfo/CodeView/CMakeLists.txt b/unittests/DebugInfo/CodeView/CMakeLists.txt
index 854182c4efb4..9576d45e77ba 100644
--- a/unittests/DebugInfo/CodeView/CMakeLists.txt
+++ b/unittests/DebugInfo/CodeView/CMakeLists.txt
@@ -4,6 +4,7 @@ set(LLVM_LINK_COMPONENTS
set(DebugInfoCodeViewSources
RandomAccessVisitorTest.cpp
+ TypeIndexDiscoveryTest.cpp
)
add_llvm_unittest(DebugInfoCodeViewTests
diff --git a/unittests/DebugInfo/CodeView/ErrorChecking.h b/unittests/DebugInfo/CodeView/ErrorChecking.h
index 09310883bf58..4ca74c487b3e 100644
--- a/unittests/DebugInfo/CodeView/ErrorChecking.h
+++ b/unittests/DebugInfo/CodeView/ErrorChecking.h
@@ -26,6 +26,15 @@
consumeError(std::move(E)); \
}
+#define ASSERT_EXPECTED(Exp) \
+ { \
+ auto E = Exp.takeError(); \
+ bool Success = static_cast<bool>(E); \
+ if (!Success) \
+ consumeError(std::move(E)); \
+ ASSERT_FALSE(Success); \
+ }
+
#define EXPECT_EXPECTED(Exp) \
{ \
auto E = Exp.takeError(); \
diff --git a/unittests/DebugInfo/CodeView/TypeIndexDiscoveryTest.cpp b/unittests/DebugInfo/CodeView/TypeIndexDiscoveryTest.cpp
new file mode 100644
index 000000000000..4eca7777a1e2
--- /dev/null
+++ b/unittests/DebugInfo/CodeView/TypeIndexDiscoveryTest.cpp
@@ -0,0 +1,496 @@
+//===- llvm/unittest/DebugInfo/CodeView/TypeIndexDiscoveryTest.cpp --------===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#include "llvm/DebugInfo/CodeView/TypeIndexDiscovery.h"
+
+#include "ErrorChecking.h"
+#include "llvm/DebugInfo/CodeView/TypeTableBuilder.h"
+#include "llvm/Support/Allocator.h"
+
+#include "gmock/gmock.h"
+#include "gtest/gtest.h"
+
+using namespace llvm;
+using namespace llvm::codeview;
+
+class TypeIndexIteratorTest : public testing::Test {
+public:
+ TypeIndexIteratorTest() {}
+
+ void SetUp() override {
+ Refs.clear();
+ TTB = make_unique<TypeTableBuilder>(Storage);
+ FLRB = make_unique<FieldListRecordBuilder>(*TTB);
+ }
+
+ void TearDown() override {
+ FLRB.reset();
+ TTB.reset();
+ }
+
+protected:
+ template <typename... Indices>
+ bool checkTypeReferences(uint32_t RecordIndex, Indices &&... TIs) const {
+ EXPECT_EQ(sizeof...(Indices), countRefs(RecordIndex));
+ return checkTypeReferencesImpl(RecordIndex, std::forward<Indices>(TIs)...);
+ }
+
+ template <typename... T> void writeFieldList(T &&... MemberRecords) {
+ FLRB->begin();
+ writeFieldListImpl(std::forward<T>(MemberRecords)...);
+ FLRB->end(true);
+ ASSERT_EQ(1u, TTB->records().size());
+ discoverAllTypeIndices();
+ }
+
+ template <typename... T> void writeTypeRecords(T &&... Records) {
+ writeTypeRecordsImpl(std::forward<T>(Records)...);
+ ASSERT_EQ(sizeof...(T), TTB->records().size());
+ discoverAllTypeIndices();
+ }
+
+ std::unique_ptr<TypeTableBuilder> TTB;
+
+private:
+ uint32_t countRefs(uint32_t RecordIndex) const {
+ auto &R = Refs[RecordIndex];
+ uint32_t Count = 0;
+ for (auto &Ref : R) {
+ Count += Ref.Count;
+ }
+ return Count;
+ }
+
+ bool checkOneTypeReference(uint32_t RecordIndex, ArrayRef<uint8_t> RecordData,
+ TypeIndex TI) const {
+ RecordData = RecordData.drop_front(sizeof(RecordPrefix));
+ auto &RefList = Refs[RecordIndex];
+ for (auto &Ref : RefList) {
+ uint32_t Offset = Ref.Offset;
+ ArrayRef<uint8_t> Loc = RecordData.drop_front(Offset);
+ ArrayRef<TypeIndex> Indices(
+ reinterpret_cast<const TypeIndex *>(Loc.data()), Ref.Count);
+ if (llvm::any_of(Indices,
+ [TI](const TypeIndex &Other) { return Other == TI; }))
+ return true;
+ }
+ return false;
+ }
+
+ template <typename... Indices>
+ bool checkTypeReferencesImpl(uint32_t RecordIndex) const {
+ return true;
+ }
+
+ template <typename... Indices>
+ bool checkTypeReferencesImpl(uint32_t RecordIndex, TypeIndex TI,
+ Indices &&... Rest) const {
+ ArrayRef<uint8_t> Record = TTB->records()[RecordIndex];
+ bool Success = checkOneTypeReference(RecordIndex, Record, TI);
+ EXPECT_TRUE(Success);
+ return Success &
+ checkTypeReferencesImpl(RecordIndex, std::forward<Indices>(Rest)...);
+ }
+
+ void discoverAllTypeIndices() {
+ Refs.resize(TTB->records().size());
+ for (uint32_t I = 0; I < TTB->records().size(); ++I) {
+ ArrayRef<uint8_t> Data = TTB->records()[I];
+ discoverTypeIndices(Data, Refs[I]);
+ }
+ }
+
+ // Helper function to write out a field list record with the given list
+ // of member records.
+ void writeFieldListImpl() {}
+
+ template <typename RecType, typename... Rest>
+ void writeFieldListImpl(RecType &&Record, Rest &&... Records) {
+ FLRB->writeMemberType(Record);
+ writeFieldListImpl(std::forward<Rest>(Records)...);
+ }
+
+ // Helper function to write out a list of type records.
+ void writeTypeRecordsImpl() {}
+
+ template <typename RecType, typename... Rest>
+ void writeTypeRecordsImpl(RecType &&Record, Rest &&... Records) {
+ TTB->writeKnownType(Record);
+ writeTypeRecordsImpl(std::forward<Rest>(Records)...);
+ }
+
+ std::vector<SmallVector<TiReference, 4>> Refs;
+ std::unique_ptr<FieldListRecordBuilder> FLRB;
+ BumpPtrAllocator Storage;
+};
+
+namespace leafs {
+static FuncIdRecord FuncId(TypeIndex(1), TypeIndex(2), "FuncId");
+static MemberFuncIdRecord MemFuncId(TypeIndex(3), TypeIndex(4), "FuncId");
+static StringIdRecord StringId(TypeIndex(5), "TheString");
+static struct {
+ std::vector<TypeIndex> Ids = {TypeIndex(6), TypeIndex(7), TypeIndex(8)};
+ StringListRecord Record{TypeRecordKind::StringList, Ids};
+} StringList;
+static struct {
+ std::vector<TypeIndex> Ids = {TypeIndex(9), TypeIndex(10), TypeIndex(11)};
+ BuildInfoRecord Record{Ids};
+} BuildInfo;
+static UdtSourceLineRecord UdtSourceLine(TypeIndex(12), TypeIndex(13), 0);
+static UdtModSourceLineRecord UdtModSourceLine(TypeIndex(14), TypeIndex(15), 0,
+ 0);
+static ModifierRecord Modifier(TypeIndex(16), ModifierOptions::None);
+static ProcedureRecord Procedure(TypeIndex(17), CallingConvention::PpcCall,
+ FunctionOptions::None, 0, TypeIndex(18));
+static MemberFunctionRecord MemberFunction(TypeIndex(19), TypeIndex(20),
+ TypeIndex(21),
+ CallingConvention::ThisCall,
+ FunctionOptions::None, 2,
+ TypeIndex(22), 0);
+static struct {
+ std::vector<TypeIndex> Ids = {TypeIndex(23), TypeIndex(24), TypeIndex(25)};
+ ArgListRecord Record{TypeRecordKind::ArgList, Ids};
+} ArgList;
+static ArrayRecord Array(TypeIndex(26), TypeIndex(27), 10, "MyArray");
+static ClassRecord Class(TypeRecordKind::Class, 3, ClassOptions::None,
+ TypeIndex(28), TypeIndex(29), TypeIndex(30), 10,
+ "MyClass", "MyClassUniqueName");
+static ClassRecord Struct(TypeRecordKind::Struct, 3, ClassOptions::None,
+ TypeIndex(31), TypeIndex(32), TypeIndex(33), 10,
+ "MyClass", "MyClassUniqueName");
+static UnionRecord Union(1, ClassOptions::None, TypeIndex(34), 10, "MyUnion",
+ "MyUnionUniqueName");
+static EnumRecord Enum(1, ClassOptions::None, TypeIndex(35), "MyEnum",
+ "EnumUniqueName", TypeIndex(36));
+static BitFieldRecord BitField(TypeIndex(37), 1, 0);
+static VFTableRecord VFTable(TypeIndex(38), TypeIndex(39), 1, "VFT", {});
+static VFTableShapeRecord VTableShape({});
+static struct {
+ const TypeIndex T1{40};
+ const TypeIndex T2{41};
+ const TypeIndex T3{42};
+ const TypeIndex T4{43};
+
+ std::vector<OneMethodRecord> Methods{
+ {T1, MemberAccess::Public, MethodKind::IntroducingVirtual,
+ MethodOptions::None, 0, "Method1"},
+ {T2, MemberAccess::Public, MethodKind::PureVirtual, MethodOptions::None,
+ 0, "Method1"},
+ {T3, MemberAccess::Public, MethodKind::PureIntroducingVirtual,
+ MethodOptions::None, 0, "Method1"},
+ {T4, MemberAccess::Public, MethodKind::Static, MethodOptions::None, 0,
+ "Method1"}};
+
+ MethodOverloadListRecord Record{Methods};
+} MethodOverloadList;
+static PointerRecord Pointer(TypeIndex(44), PointerKind::Near32,
+ PointerMode::Pointer, PointerOptions::Const, 3);
+static PointerRecord MemberPointer(
+ TypeIndex(45), PointerKind::Near32, PointerMode::PointerToDataMember,
+ PointerOptions::Const, 3,
+ MemberPointerInfo(TypeIndex(46),
+ PointerToMemberRepresentation::GeneralData));
+}
+
+namespace members {
+static BaseClassRecord BaseClass(MemberAccess::Public, TypeIndex(47), 0);
+static EnumeratorRecord Enumerator(MemberAccess::Public,
+ APSInt(APInt(8, 3, false)), "Test");
+DataMemberRecord DataMember(MemberAccess::Public, TypeIndex(48), 0, "Test");
+OverloadedMethodRecord OverloadedMethod(3, TypeIndex(49), "MethodList");
+static struct {
+ const TypeIndex T1{50};
+ const TypeIndex T2{51};
+ const TypeIndex T3{52};
+ const TypeIndex T4{53};
+ OneMethodRecord R1{T1,
+ MemberAccess::Public,
+ MethodKind::IntroducingVirtual,
+ MethodOptions::None,
+ 0,
+ "M1"};
+ OneMethodRecord R2{T2,
+ MemberAccess::Public,
+ MethodKind::PureVirtual,
+ MethodOptions::None,
+ 0,
+ "M2"};
+ OneMethodRecord R3{T3,
+ MemberAccess::Public,
+ MethodKind::PureIntroducingVirtual,
+ MethodOptions::None,
+ 0,
+ "M3"};
+ OneMethodRecord R4{T4,
+ MemberAccess::Protected,
+ MethodKind::Vanilla,
+ MethodOptions::CompilerGenerated,
+ 0,
+ "M4"};
+} OneMethod;
+static NestedTypeRecord NestedType(TypeIndex(54), "MyClass");
+static StaticDataMemberRecord StaticDataMember(MemberAccess::Public,
+ TypeIndex(55), "Foo");
+static VirtualBaseClassRecord VirtualBaseClass(TypeRecordKind::VirtualBaseClass,
+ MemberAccess::Public,
+ TypeIndex(56), TypeIndex(57), 0,
+ 0);
+static VFPtrRecord VFPtr(TypeIndex(58));
+static ListContinuationRecord Continuation(TypeIndex(59));
+}
+
+TEST_F(TypeIndexIteratorTest, FuncId) {
+ using namespace leafs;
+ writeTypeRecords(FuncId);
+ checkTypeReferences(0, FuncId.FunctionType, FuncId.ParentScope);
+}
+
+TEST_F(TypeIndexIteratorTest, MemFuncId) {
+ using namespace leafs;
+ writeTypeRecords(MemFuncId);
+ checkTypeReferences(0, MemFuncId.ClassType, MemFuncId.FunctionType);
+}
+
+TEST_F(TypeIndexIteratorTest, StringId) {
+ using namespace leafs;
+ writeTypeRecords(StringId);
+ checkTypeReferences(0, StringId.Id);
+}
+
+TEST_F(TypeIndexIteratorTest, SubstrList) {
+ using namespace leafs;
+ writeTypeRecords(StringList.Record);
+ checkTypeReferences(0, StringList.Ids[0], StringList.Ids[1],
+ StringList.Ids[2]);
+}
+
+TEST_F(TypeIndexIteratorTest, BuildInfo) {
+ using namespace leafs;
+ writeTypeRecords(BuildInfo.Record);
+ checkTypeReferences(0, BuildInfo.Ids[0], BuildInfo.Ids[1], BuildInfo.Ids[2]);
+}
+
+TEST_F(TypeIndexIteratorTest, UdtSrcLine) {
+ using namespace leafs;
+ writeTypeRecords(UdtSourceLine);
+ checkTypeReferences(0, UdtSourceLine.UDT, UdtSourceLine.SourceFile);
+}
+
+TEST_F(TypeIndexIteratorTest, UdtModSrcLine) {
+ using namespace leafs;
+ writeTypeRecords(UdtModSourceLine);
+ checkTypeReferences(0, UdtModSourceLine.UDT, UdtModSourceLine.SourceFile);
+}
+
+TEST_F(TypeIndexIteratorTest, Modifier) {
+ using namespace leafs;
+ writeTypeRecords(Modifier);
+ checkTypeReferences(0, Modifier.ModifiedType);
+}
+
+TEST_F(TypeIndexIteratorTest, Procedure) {
+ using namespace leafs;
+ writeTypeRecords(Procedure);
+ checkTypeReferences(0, Procedure.ReturnType, Procedure.ArgumentList);
+}
+
+TEST_F(TypeIndexIteratorTest, MemFunc) {
+ using namespace leafs;
+ writeTypeRecords(MemberFunction);
+ checkTypeReferences(0, MemberFunction.ReturnType, MemberFunction.ClassType,
+ MemberFunction.ThisType, MemberFunction.ArgumentList);
+}
+
+TEST_F(TypeIndexIteratorTest, ArgList) {
+ using namespace leafs;
+ writeTypeRecords(ArgList.Record);
+ checkTypeReferences(0, ArgList.Ids[0], ArgList.Ids[1], ArgList.Ids[2]);
+}
+
+TEST_F(TypeIndexIteratorTest, Array) {
+ using namespace leafs;
+ writeTypeRecords(Array);
+ checkTypeReferences(0, Array.ElementType, Array.IndexType);
+}
+
+TEST_F(TypeIndexIteratorTest, Class) {
+ using namespace leafs;
+ writeTypeRecords(Class);
+ checkTypeReferences(0, Class.FieldList, Class.DerivationList,
+ Class.VTableShape);
+}
+
+TEST_F(TypeIndexIteratorTest, Struct) {
+ using namespace leafs;
+ writeTypeRecords(Struct);
+ checkTypeReferences(0, Struct.FieldList, Struct.DerivationList,
+ Struct.VTableShape);
+}
+
+TEST_F(TypeIndexIteratorTest, Union) {
+ using namespace leafs;
+ writeTypeRecords(Union);
+ checkTypeReferences(0, Union.FieldList);
+}
+
+TEST_F(TypeIndexIteratorTest, Enum) {
+ using namespace leafs;
+ writeTypeRecords(Enum);
+ checkTypeReferences(0, Enum.FieldList, Enum.UnderlyingType);
+}
+
+TEST_F(TypeIndexIteratorTest, Bitfield) {
+ using namespace leafs;
+ writeTypeRecords(BitField);
+ checkTypeReferences(0, BitField.Type);
+}
+
+TEST_F(TypeIndexIteratorTest, VTable) {
+ using namespace leafs;
+ writeTypeRecords(VFTable);
+ checkTypeReferences(0, VFTable.CompleteClass, VFTable.OverriddenVFTable);
+}
+
+TEST_F(TypeIndexIteratorTest, VTShape) {
+ using namespace leafs;
+ writeTypeRecords(VTableShape);
+ checkTypeReferences(0);
+}
+
+TEST_F(TypeIndexIteratorTest, OverloadList) {
+ using namespace leafs;
+ writeTypeRecords(MethodOverloadList.Record);
+ checkTypeReferences(0, MethodOverloadList.T1, MethodOverloadList.T2,
+ MethodOverloadList.T3, MethodOverloadList.T4);
+}
+
+TEST_F(TypeIndexIteratorTest, Pointer) {
+ using namespace leafs;
+ writeTypeRecords(Pointer);
+ checkTypeReferences(0, Pointer.ReferentType);
+}
+
+TEST_F(TypeIndexIteratorTest, MemberPointer) {
+ using namespace leafs;
+ writeTypeRecords(MemberPointer);
+ checkTypeReferences(0, MemberPointer.ReferentType,
+ MemberPointer.MemberInfo->ContainingType);
+}
+
+TEST_F(TypeIndexIteratorTest, ManyTypes) {
+
+ using namespace leafs;
+ writeTypeRecords(FuncId, MemFuncId, StringId, StringList.Record,
+ BuildInfo.Record, UdtSourceLine, UdtModSourceLine, Modifier,
+ Procedure, MemberFunction, ArgList.Record, Array, Class,
+ Union, Enum, BitField, VFTable, VTableShape,
+ MethodOverloadList.Record, Pointer, MemberPointer);
+
+ checkTypeReferences(0, FuncId.FunctionType, FuncId.ParentScope);
+ checkTypeReferences(1, MemFuncId.ClassType, MemFuncId.FunctionType);
+ checkTypeReferences(2, StringId.Id);
+ checkTypeReferences(3, StringList.Ids[0], StringList.Ids[1],
+ StringList.Ids[2]);
+ checkTypeReferences(4, BuildInfo.Ids[0], BuildInfo.Ids[1], BuildInfo.Ids[2]);
+ checkTypeReferences(5, UdtSourceLine.UDT, UdtSourceLine.SourceFile);
+ checkTypeReferences(6, UdtModSourceLine.UDT, UdtModSourceLine.SourceFile);
+ checkTypeReferences(7, Modifier.ModifiedType);
+ checkTypeReferences(8, Procedure.ReturnType, Procedure.ArgumentList);
+ checkTypeReferences(9, MemberFunction.ReturnType, MemberFunction.ClassType,
+ MemberFunction.ThisType, MemberFunction.ArgumentList);
+ checkTypeReferences(10, ArgList.Ids[0], ArgList.Ids[1], ArgList.Ids[2]);
+ checkTypeReferences(11, Array.ElementType, Array.IndexType);
+ checkTypeReferences(12, Class.FieldList, Class.DerivationList,
+ Class.VTableShape);
+ checkTypeReferences(13, Union.FieldList);
+ checkTypeReferences(14, Enum.FieldList, Enum.UnderlyingType);
+ checkTypeReferences(15, BitField.Type);
+ checkTypeReferences(16, VFTable.CompleteClass, VFTable.OverriddenVFTable);
+ checkTypeReferences(17);
+ checkTypeReferences(18, MethodOverloadList.T1, MethodOverloadList.T2,
+ MethodOverloadList.T3, MethodOverloadList.T4);
+ checkTypeReferences(19, Pointer.ReferentType);
+ checkTypeReferences(20, MemberPointer.ReferentType,
+ MemberPointer.MemberInfo->ContainingType);
+}
+
+TEST_F(TypeIndexIteratorTest, FieldListBaseClass) {
+ using namespace members;
+ writeFieldList(BaseClass);
+ checkTypeReferences(0, BaseClass.Type);
+}
+
+TEST_F(TypeIndexIteratorTest, FieldListEnumerator) {
+ using namespace members;
+ writeFieldList(Enumerator);
+ checkTypeReferences(0);
+}
+
+TEST_F(TypeIndexIteratorTest, FieldListMember) {
+ using namespace members;
+ writeFieldList(DataMember);
+ checkTypeReferences(0, DataMember.Type);
+}
+
+TEST_F(TypeIndexIteratorTest, FieldListMethod) {
+ using namespace members;
+ writeFieldList(OverloadedMethod);
+ checkTypeReferences(0, OverloadedMethod.MethodList);
+}
+
+TEST_F(TypeIndexIteratorTest, FieldListOneMethod) {
+ using namespace members;
+ writeFieldList(OneMethod.R1, OneMethod.R2, OneMethod.R3, OneMethod.R4);
+ checkTypeReferences(0, OneMethod.T1, OneMethod.T2, OneMethod.T3,
+ OneMethod.T4);
+}
+
+TEST_F(TypeIndexIteratorTest, FieldListNestedType) {
+ using namespace members;
+ writeFieldList(NestedType);
+ checkTypeReferences(0, NestedType.Type);
+}
+
+TEST_F(TypeIndexIteratorTest, FieldListStaticMember) {
+ using namespace members;
+ writeFieldList(StaticDataMember);
+ checkTypeReferences(0, StaticDataMember.Type);
+}
+
+TEST_F(TypeIndexIteratorTest, FieldListVirtualBase) {
+ using namespace members;
+ writeFieldList(VirtualBaseClass);
+ checkTypeReferences(0, VirtualBaseClass.BaseType, VirtualBaseClass.VBPtrType);
+}
+
+TEST_F(TypeIndexIteratorTest, FieldListVFTable) {
+ using namespace members;
+ writeFieldList(VFPtr);
+ checkTypeReferences(0, VFPtr.Type);
+}
+
+TEST_F(TypeIndexIteratorTest, FieldListContinuation) {
+ using namespace members;
+ writeFieldList(Continuation);
+ checkTypeReferences(0, Continuation.ContinuationIndex);
+}
+
+TEST_F(TypeIndexIteratorTest, ManyMembers) {
+ using namespace members;
+ writeFieldList(BaseClass, Enumerator, DataMember, OverloadedMethod,
+ OneMethod.R1, OneMethod.R2, OneMethod.R3, OneMethod.R4,
+ NestedType, StaticDataMember, VirtualBaseClass, VFPtr,
+ Continuation);
+
+ checkTypeReferences(
+ 0, BaseClass.Type, DataMember.Type, OverloadedMethod.MethodList,
+ OneMethod.T1, OneMethod.T2, OneMethod.T3, OneMethod.T4, NestedType.Type,
+ StaticDataMember.Type, VirtualBaseClass.BaseType,
+ VirtualBaseClass.VBPtrType, VFPtr.Type, Continuation.ContinuationIndex);
+} \ No newline at end of file
diff --git a/unittests/DebugInfo/DWARF/DWARFDebugInfoTest.cpp b/unittests/DebugInfo/DWARF/DWARFDebugInfoTest.cpp
index a9d0d9ef4e69..9e846674648c 100644
--- a/unittests/DebugInfo/DWARF/DWARFDebugInfoTest.cpp
+++ b/unittests/DebugInfo/DWARF/DWARFDebugInfoTest.cpp
@@ -311,8 +311,9 @@ void TestAllForms() {
EXPECT_EQ(Data2, toReference(DieDG.find(Attr_DW_FORM_ref2), 0));
EXPECT_EQ(Data4, toReference(DieDG.find(Attr_DW_FORM_ref4), 0));
EXPECT_EQ(Data8, toReference(DieDG.find(Attr_DW_FORM_ref8), 0));
- if (Version >= 4)
+ if (Version >= 4) {
EXPECT_EQ(Data8_2, toReference(DieDG.find(Attr_DW_FORM_ref_sig8), 0));
+ }
EXPECT_EQ(UData[0], toReference(DieDG.find(Attr_DW_FORM_ref_udata), 0));
//----------------------------------------------------------------------
@@ -320,15 +321,17 @@ void TestAllForms() {
//----------------------------------------------------------------------
EXPECT_EQ(1ULL, toUnsigned(DieDG.find(Attr_DW_FORM_flag_true), 0));
EXPECT_EQ(0ULL, toUnsigned(DieDG.find(Attr_DW_FORM_flag_false), 1));
- if (Version >= 4)
+ if (Version >= 4) {
EXPECT_EQ(1ULL, toUnsigned(DieDG.find(Attr_DW_FORM_flag_present), 0));
+ }
//----------------------------------------------------------------------
// Test SLEB128 based forms
//----------------------------------------------------------------------
EXPECT_EQ(SData, toSigned(DieDG.find(Attr_DW_FORM_sdata), 0));
- if (Version >= 5)
+ if (Version >= 5) {
EXPECT_EQ(ICSData, toSigned(DieDG.find(Attr_DW_FORM_implicit_const), 0));
+ }
//----------------------------------------------------------------------
// Test ULEB128 based forms
@@ -340,9 +343,10 @@ void TestAllForms() {
//----------------------------------------------------------------------
EXPECT_EQ(Dwarf32Values[0],
toReference(DieDG.find(Attr_DW_FORM_GNU_ref_alt), 0));
- if (Version >= 4)
+ if (Version >= 4) {
EXPECT_EQ(Dwarf32Values[1],
toSectionOffset(DieDG.find(Attr_DW_FORM_sec_offset), 0));
+ }
//----------------------------------------------------------------------
// Add an address at the end to make sure we can decode this value
@@ -849,8 +853,8 @@ template <uint16_t Version, class AddrType> void TestAddresses() {
// Get the compile unit DIE is valid.
auto DieDG = U->getUnitDIE(false);
EXPECT_TRUE(DieDG.isValid());
-
- uint64_t LowPC, HighPC;
+
+ uint64_t LowPC, HighPC, SectionIndex;
Optional<uint64_t> OptU64;
// Verify the that our subprogram with no PC value fails appropriately when
// asked for any PC values.
@@ -861,14 +865,14 @@ template <uint16_t Version, class AddrType> void TestAddresses() {
EXPECT_FALSE((bool)OptU64);
OptU64 = toAddress(SubprogramDieNoPC.find(DW_AT_high_pc));
EXPECT_FALSE((bool)OptU64);
- EXPECT_FALSE(SubprogramDieNoPC.getLowAndHighPC(LowPC, HighPC));
+ EXPECT_FALSE(SubprogramDieNoPC.getLowAndHighPC(LowPC, HighPC, SectionIndex));
OptU64 = toAddress(SubprogramDieNoPC.find(DW_AT_high_pc));
EXPECT_FALSE((bool)OptU64);
OptU64 = toUnsigned(SubprogramDieNoPC.find(DW_AT_high_pc));
EXPECT_FALSE((bool)OptU64);
OptU64 = SubprogramDieNoPC.getHighPC(ActualLowPC);
EXPECT_FALSE((bool)OptU64);
- EXPECT_FALSE(SubprogramDieNoPC.getLowAndHighPC(LowPC, HighPC));
+ EXPECT_FALSE(SubprogramDieNoPC.getLowAndHighPC(LowPC, HighPC, SectionIndex));
// Verify the that our subprogram with only a low PC value succeeds when
// we ask for the Low PC, but fails appropriately when asked for the high PC
@@ -885,7 +889,7 @@ template <uint16_t Version, class AddrType> void TestAddresses() {
EXPECT_FALSE((bool)OptU64);
OptU64 = SubprogramDieLowPC.getHighPC(ActualLowPC);
EXPECT_FALSE((bool)OptU64);
- EXPECT_FALSE(SubprogramDieLowPC.getLowAndHighPC(LowPC, HighPC));
+ EXPECT_FALSE(SubprogramDieLowPC.getLowAndHighPC(LowPC, HighPC, SectionIndex));
// Verify the that our subprogram with only a low PC value succeeds when
// we ask for the Low PC, but fails appropriately when asked for the high PC
@@ -919,7 +923,7 @@ template <uint16_t Version, class AddrType> void TestAddresses() {
EXPECT_TRUE((bool)OptU64);
EXPECT_EQ(OptU64.getValue(), ActualHighPC);
- EXPECT_TRUE(SubprogramDieLowHighPC.getLowAndHighPC(LowPC, HighPC));
+ EXPECT_TRUE(SubprogramDieLowHighPC.getLowAndHighPC(LowPC, HighPC, SectionIndex));
EXPECT_EQ(LowPC, ActualLowPC);
EXPECT_EQ(HighPC, ActualHighPC);
}
diff --git a/unittests/DebugInfo/PDB/MappedBlockStreamTest.cpp b/unittests/DebugInfo/PDB/MappedBlockStreamTest.cpp
index 9f8940b77f28..9d90e265df33 100644
--- a/unittests/DebugInfo/PDB/MappedBlockStreamTest.cpp
+++ b/unittests/DebugInfo/PDB/MappedBlockStreamTest.cpp
@@ -75,12 +75,19 @@ private:
MutableArrayRef<uint8_t> Data;
};
+TEST(MappedBlockStreamTest, NumBlocks) {
+ DiscontiguousStream F(BlocksAry, DataAry);
+ auto S = MappedBlockStream::createStream(F.block_size(), F.layout(), F);
+ EXPECT_EQ(F.block_size(), S->getBlockSize());
+ EXPECT_EQ(F.layout().Blocks.size(), S->getNumBlocks());
+
+}
+
// Tests that a read which is entirely contained within a single block works
// and does not allocate.
TEST(MappedBlockStreamTest, ReadBeyondEndOfStreamRef) {
DiscontiguousStream F(BlocksAry, DataAry);
- auto S = MappedBlockStream::createStream(F.block_size(), F.block_count(),
- F.layout(), F);
+ auto S = MappedBlockStream::createStream(F.block_size(), F.layout(), F);
BinaryStreamReader R(*S);
BinaryStreamRef SR;
@@ -95,8 +102,7 @@ TEST(MappedBlockStreamTest, ReadBeyondEndOfStreamRef) {
// does not fail due to the length of the output buffer.
TEST(MappedBlockStreamTest, ReadOntoNonEmptyBuffer) {
DiscontiguousStream F(BlocksAry, DataAry);
- auto S = MappedBlockStream::createStream(F.block_size(), F.block_count(),
- F.layout(), F);
+ auto S = MappedBlockStream::createStream(F.block_size(), F.layout(), F);
BinaryStreamReader R(*S);
StringRef Str = "ZYXWVUTSRQPONMLKJIHGFEDCBA";
@@ -110,7 +116,7 @@ TEST(MappedBlockStreamTest, ReadOntoNonEmptyBuffer) {
// not allocate memory.
TEST(MappedBlockStreamTest, ZeroCopyReadContiguousBreak) {
DiscontiguousStream F(BlocksAry, DataAry);
- auto S = MappedBlockStream::createStream(F.block_size(), F.block_count(),
+ auto S = MappedBlockStream::createStream(F.block_size(),
F.layout(), F);
BinaryStreamReader R(*S);
StringRef Str;
@@ -129,8 +135,7 @@ TEST(MappedBlockStreamTest, ZeroCopyReadContiguousBreak) {
// requested.
TEST(MappedBlockStreamTest, CopyReadNonContiguousBreak) {
DiscontiguousStream F(BlocksAry, DataAry);
- auto S = MappedBlockStream::createStream(F.block_size(), F.block_count(),
- F.layout(), F);
+ auto S = MappedBlockStream::createStream(F.block_size(), F.layout(), F);
BinaryStreamReader R(*S);
StringRef Str;
EXPECT_NO_ERROR(R.readFixedString(Str, 10));
@@ -142,8 +147,7 @@ TEST(MappedBlockStreamTest, CopyReadNonContiguousBreak) {
// fails and allocates no memory.
TEST(MappedBlockStreamTest, InvalidReadSizeNoBreak) {
DiscontiguousStream F(BlocksAry, DataAry);
- auto S = MappedBlockStream::createStream(F.block_size(), F.block_count(),
- F.layout(), F);
+ auto S = MappedBlockStream::createStream(F.block_size(), F.layout(), F);
BinaryStreamReader R(*S);
StringRef Str;
@@ -156,8 +160,7 @@ TEST(MappedBlockStreamTest, InvalidReadSizeNoBreak) {
// fails and allocates no memory.
TEST(MappedBlockStreamTest, InvalidReadSizeContiguousBreak) {
DiscontiguousStream F(BlocksAry, DataAry);
- auto S = MappedBlockStream::createStream(F.block_size(), F.block_count(),
- F.layout(), F);
+ auto S = MappedBlockStream::createStream(F.block_size(), F.layout(), F);
BinaryStreamReader R(*S);
StringRef Str;
@@ -170,8 +173,7 @@ TEST(MappedBlockStreamTest, InvalidReadSizeContiguousBreak) {
// boundary fails and allocates no memory.
TEST(MappedBlockStreamTest, InvalidReadSizeNonContiguousBreak) {
DiscontiguousStream F(BlocksAry, DataAry);
- auto S = MappedBlockStream::createStream(F.block_size(), F.block_count(),
- F.layout(), F);
+ auto S = MappedBlockStream::createStream(F.block_size(), F.layout(), F);
BinaryStreamReader R(*S);
StringRef Str;
@@ -183,8 +185,7 @@ TEST(MappedBlockStreamTest, InvalidReadSizeNonContiguousBreak) {
// beyond the end of a StreamRef fails.
TEST(MappedBlockStreamTest, ZeroCopyReadNoBreak) {
DiscontiguousStream F(BlocksAry, DataAry);
- auto S = MappedBlockStream::createStream(F.block_size(), F.block_count(),
- F.layout(), F);
+ auto S = MappedBlockStream::createStream(F.block_size(), F.layout(), F);
BinaryStreamReader R(*S);
StringRef Str;
EXPECT_NO_ERROR(R.readFixedString(Str, 1));
@@ -197,8 +198,7 @@ TEST(MappedBlockStreamTest, ZeroCopyReadNoBreak) {
// previous allocation.
TEST(MappedBlockStreamTest, UnalignedOverlappingRead) {
DiscontiguousStream F(BlocksAry, DataAry);
- auto S = MappedBlockStream::createStream(F.block_size(), F.block_count(),
- F.layout(), F);
+ auto S = MappedBlockStream::createStream(F.block_size(), F.layout(), F);
BinaryStreamReader R(*S);
StringRef Str1;
StringRef Str2;
@@ -218,8 +218,7 @@ TEST(MappedBlockStreamTest, UnalignedOverlappingRead) {
// still works correctly and allocates again from the shared pool.
TEST(MappedBlockStreamTest, UnalignedOverlappingReadFail) {
DiscontiguousStream F(BlocksAry, DataAry);
- auto S = MappedBlockStream::createStream(F.block_size(), F.block_count(),
- F.layout(), F);
+ auto S = MappedBlockStream::createStream(F.block_size(), F.layout(), F);
BinaryStreamReader R(*S);
StringRef Str1;
StringRef Str2;
@@ -243,7 +242,7 @@ TEST(MappedBlockStreamTest, WriteBeyondEndOfStream) {
DiscontiguousStream F(BlocksAry, Data);
auto S = WritableMappedBlockStream::createStream(
- F.block_size(), F.block_count(), F.layout(), F);
+ F.block_size(), F.layout(), F);
ArrayRef<uint8_t> Buffer;
EXPECT_ERROR(S->writeBytes(0, ArrayRef<uint8_t>(LargeBuffer)));
@@ -256,7 +255,7 @@ TEST(MappedBlockStreamTest, TestWriteBytesNoBreakBoundary) {
static uint8_t Data[] = {'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J'};
DiscontiguousStream F(BlocksAry, Data);
auto S = WritableMappedBlockStream::createStream(
- F.block_size(), F.block_count(), F.layout(), F);
+ F.block_size(), F.layout(), F);
ArrayRef<uint8_t> Buffer;
EXPECT_NO_ERROR(S->readBytes(0, 1, Buffer));
@@ -289,7 +288,7 @@ TEST(MappedBlockStreamTest, TestWriteBytesBreakBoundary) {
DiscontiguousStream F(BlocksAry, Data);
auto S = WritableMappedBlockStream::createStream(
- F.block_size(), F.block_count(), F.layout(), F);
+ F.block_size(), F.layout(), F);
ArrayRef<uint8_t> Buffer;
EXPECT_NO_ERROR(S->writeBytes(0, TestData));
@@ -308,7 +307,7 @@ TEST(MappedBlockStreamTest, TestWriteThenRead) {
DiscontiguousStream F(Blocks, Data);
auto S = WritableMappedBlockStream::createStream(
- F.block_size(), F.block_count(), F.layout(), F);
+ F.block_size(), F.layout(), F);
enum class MyEnum : uint32_t { Val1 = 2908234, Val2 = 120891234 };
using support::ulittle32_t;
@@ -400,7 +399,7 @@ TEST(MappedBlockStreamTest, TestWriteContiguousStreamRef) {
DiscontiguousStream F(DestBlocks, DestData);
auto DestStream = WritableMappedBlockStream::createStream(
- F.block_size(), F.block_count(), F.layout(), F);
+ F.block_size(), F.layout(), F);
// First write "Test Str" into the source stream.
MutableBinaryByteStream SourceStream(SrcData, little);
@@ -435,9 +434,9 @@ TEST(MappedBlockStreamTest, TestWriteDiscontiguousStreamRef) {
DiscontiguousStream SrcF(SrcBlocks, SrcData);
auto Dest = WritableMappedBlockStream::createStream(
- DestF.block_size(), DestF.block_count(), DestF.layout(), DestF);
+ DestF.block_size(), DestF.layout(), DestF);
auto Src = WritableMappedBlockStream::createStream(
- SrcF.block_size(), SrcF.block_count(), SrcF.layout(), SrcF);
+ SrcF.block_size(), SrcF.layout(), SrcF);
// First write "Test Str" into the source stream.
BinaryStreamWriter SourceWriter(*Src);
diff --git a/unittests/IR/BasicBlockTest.cpp b/unittests/IR/BasicBlockTest.cpp
new file mode 100644
index 000000000000..f1777e35b82c
--- /dev/null
+++ b/unittests/IR/BasicBlockTest.cpp
@@ -0,0 +1,75 @@
+//===- llvm/unittest/IR/BasicBlockTest.cpp - BasicBlock 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/IR/BasicBlock.h"
+#include "llvm/ADT/STLExtras.h"
+#include "llvm/IR/Function.h"
+#include "llvm/IR/IRBuilder.h"
+#include "llvm/IR/LLVMContext.h"
+#include "llvm/IR/Module.h"
+#include "llvm/IR/NoFolder.h"
+#include "gmock/gmock-matchers.h"
+#include "gtest/gtest.h"
+#include <memory>
+
+namespace llvm {
+namespace {
+
+TEST(BasicBlockTest, PhiRange) {
+ LLVMContext Context;
+
+ // Create the main block.
+ std::unique_ptr<BasicBlock> BB(BasicBlock::Create(Context));
+
+ // Create some predecessors of it.
+ std::unique_ptr<BasicBlock> BB1(BasicBlock::Create(Context));
+ BranchInst::Create(BB.get(), BB1.get());
+ std::unique_ptr<BasicBlock> BB2(BasicBlock::Create(Context));
+ BranchInst::Create(BB.get(), BB2.get());
+
+ // Make it a cycle.
+ auto *BI = BranchInst::Create(BB.get(), BB.get());
+
+ // Now insert some PHI nodes.
+ auto *Int32Ty = Type::getInt32Ty(Context);
+ auto *P1 = PHINode::Create(Int32Ty, /*NumReservedValues*/ 3, "phi.1", BI);
+ auto *P2 = PHINode::Create(Int32Ty, /*NumReservedValues*/ 3, "phi.2", BI);
+ auto *P3 = PHINode::Create(Int32Ty, /*NumReservedValues*/ 3, "phi.3", BI);
+
+ // Some non-PHI nodes.
+ auto *Sum = BinaryOperator::CreateAdd(P1, P2, "sum", BI);
+
+ // Now wire up the incoming values that are interesting.
+ P1->addIncoming(P2, BB.get());
+ P2->addIncoming(P1, BB.get());
+ P3->addIncoming(Sum, BB.get());
+
+ // Finally, let's iterate them, which is the thing we're trying to test.
+ // We'll use this to wire up the rest of the incoming values.
+ for (auto &PN : BB->phis()) {
+ PN.addIncoming(UndefValue::get(Int32Ty), BB1.get());
+ PN.addIncoming(UndefValue::get(Int32Ty), BB2.get());
+ }
+
+ // Test that we can use const iterators and generally that the iterators
+ // behave like iterators.
+ BasicBlock::const_phi_iterator CI;
+ CI = BB->phis().begin();
+ EXPECT_NE(CI, BB->phis().end());
+
+ // And iterate a const range.
+ for (const auto &PN : const_cast<const BasicBlock *>(BB.get())->phis()) {
+ EXPECT_EQ(BB.get(), PN.getIncomingBlock(0));
+ EXPECT_EQ(BB1.get(), PN.getIncomingBlock(1));
+ EXPECT_EQ(BB2.get(), PN.getIncomingBlock(2));
+ }
+}
+
+} // End anonymous namespace.
+} // End llvm namespace.
diff --git a/unittests/IR/CMakeLists.txt b/unittests/IR/CMakeLists.txt
index 750f638c7a42..6734de8e2d95 100644
--- a/unittests/IR/CMakeLists.txt
+++ b/unittests/IR/CMakeLists.txt
@@ -8,6 +8,7 @@ set(LLVM_LINK_COMPONENTS
set(IRSources
AsmWriterTest.cpp
AttributesTest.cpp
+ BasicBlockTest.cpp
ConstantRangeTest.cpp
ConstantsTest.cpp
DebugInfoTest.cpp
diff --git a/unittests/IR/DominatorTreeTest.cpp b/unittests/IR/DominatorTreeTest.cpp
index 498e111a31f6..d2062839a734 100644
--- a/unittests/IR/DominatorTreeTest.cpp
+++ b/unittests/IR/DominatorTreeTest.cpp
@@ -7,30 +7,73 @@
//
//===----------------------------------------------------------------------===//
-#include "llvm/IR/Dominators.h"
#include "llvm/Analysis/PostDominators.h"
#include "llvm/AsmParser/Parser.h"
#include "llvm/IR/Constants.h"
+#include "llvm/IR/Dominators.h"
#include "llvm/IR/Instructions.h"
#include "llvm/IR/LLVMContext.h"
#include "llvm/IR/Module.h"
-#include "llvm/IR/LegacyPassManager.h"
#include "llvm/Support/SourceMgr.h"
#include "gtest/gtest.h"
using namespace llvm;
-namespace llvm {
- void initializeDPassPass(PassRegistry&);
-
- namespace {
- struct DPass : public FunctionPass {
- static char ID;
- bool runOnFunction(Function &F) override {
- DominatorTree *DT =
- &getAnalysis<DominatorTreeWrapperPass>().getDomTree();
- PostDominatorTree *PDT =
- &getAnalysis<PostDominatorTreeWrapperPass>().getPostDomTree();
+/// Build the dominator tree for the function and run the Test.
+static void
+runWithDomTree(Module &M, StringRef FuncName,
+ function_ref<void(Function &F, DominatorTree *DT,
+ DominatorTreeBase<BasicBlock> *PDT)>
+ Test) {
+ auto *F = M.getFunction(FuncName);
+ ASSERT_NE(F, nullptr) << "Could not find " << FuncName;
+ // Compute the dominator tree for the function.
+ DominatorTree DT(*F);
+ DominatorTreeBase<BasicBlock> PDT(/*isPostDom*/ true);
+ PDT.recalculate(*F);
+ Test(*F, &DT, &PDT);
+}
+
+static std::unique_ptr<Module> makeLLVMModule(LLVMContext &Context,
+ StringRef ModuleStr) {
+ SMDiagnostic Err;
+ std::unique_ptr<Module> M = parseAssemblyString(ModuleStr, Err, Context);
+ assert(M && "Bad assembly?");
+ return M;
+}
+
+TEST(DominatorTree, Unreachable) {
+ StringRef ModuleString =
+ "declare i32 @g()\n"
+ "define void @f(i32 %x) personality i32 ()* @g {\n"
+ "bb0:\n"
+ " %y1 = add i32 %x, 1\n"
+ " %y2 = add i32 %x, 1\n"
+ " %y3 = invoke i32 @g() to label %bb1 unwind label %bb2\n"
+ "bb1:\n"
+ " %y4 = add i32 %x, 1\n"
+ " br label %bb4\n"
+ "bb2:\n"
+ " %y5 = landingpad i32\n"
+ " cleanup\n"
+ " br label %bb4\n"
+ "bb3:\n"
+ " %y6 = add i32 %x, 1\n"
+ " %y7 = add i32 %x, 1\n"
+ " ret void\n"
+ "bb4:\n"
+ " %y8 = phi i32 [0, %bb2], [%y4, %bb1]\n"
+ " %y9 = phi i32 [0, %bb2], [%y4, %bb1]\n"
+ " ret void\n"
+ "}\n";
+
+ // Parse the module.
+ LLVMContext Context;
+ std::unique_ptr<Module> M = makeLLVMModule(Context, ModuleString);
+
+ runWithDomTree(
+ *M, "f",
+ [&](Function &F, DominatorTree *DT, DominatorTreeBase<BasicBlock> *PDT) {
Function::iterator FI = F.begin();
BasicBlock *BB0 = &*FI++;
@@ -205,66 +248,12 @@ namespace llvm {
// Change root node
DT->verifyDomTree();
- BasicBlock *NewEntry = BasicBlock::Create(F.getContext(), "new_entry",
- &F, BB0);
+ BasicBlock *NewEntry =
+ BasicBlock::Create(F.getContext(), "new_entry", &F, BB0);
BranchInst::Create(BB0, NewEntry);
EXPECT_EQ(F.begin()->getName(), NewEntry->getName());
EXPECT_TRUE(&F.getEntryBlock() == NewEntry);
DT->setNewRoot(NewEntry);
DT->verifyDomTree();
-
- return false;
- }
- void getAnalysisUsage(AnalysisUsage &AU) const override {
- AU.addRequired<DominatorTreeWrapperPass>();
- AU.addRequired<PostDominatorTreeWrapperPass>();
- }
- DPass() : FunctionPass(ID) {
- initializeDPassPass(*PassRegistry::getPassRegistry());
- }
- };
- char DPass::ID = 0;
-
- std::unique_ptr<Module> makeLLVMModule(LLVMContext &Context, DPass *P) {
- const char *ModuleString =
- "declare i32 @g()\n" \
- "define void @f(i32 %x) personality i32 ()* @g {\n" \
- "bb0:\n" \
- " %y1 = add i32 %x, 1\n" \
- " %y2 = add i32 %x, 1\n" \
- " %y3 = invoke i32 @g() to label %bb1 unwind label %bb2\n" \
- "bb1:\n" \
- " %y4 = add i32 %x, 1\n" \
- " br label %bb4\n" \
- "bb2:\n" \
- " %y5 = landingpad i32\n" \
- " cleanup\n" \
- " br label %bb4\n" \
- "bb3:\n" \
- " %y6 = add i32 %x, 1\n" \
- " %y7 = add i32 %x, 1\n" \
- " ret void\n" \
- "bb4:\n" \
- " %y8 = phi i32 [0, %bb2], [%y4, %bb1]\n"
- " %y9 = phi i32 [0, %bb2], [%y4, %bb1]\n"
- " ret void\n" \
- "}\n";
- SMDiagnostic Err;
- return parseAssemblyString(ModuleString, Err, Context);
- }
-
- TEST(DominatorTree, Unreachable) {
- DPass *P = new DPass();
- LLVMContext Context;
- std::unique_ptr<Module> M = makeLLVMModule(Context, P);
- legacy::PassManager Passes;
- Passes.add(P);
- Passes.run(*M);
- }
- }
+ });
}
-
-INITIALIZE_PASS_BEGIN(DPass, "dpass", "dpass", false, false)
-INITIALIZE_PASS_DEPENDENCY(DominatorTreeWrapperPass)
-INITIALIZE_PASS_DEPENDENCY(PostDominatorTreeWrapperPass)
-INITIALIZE_PASS_END(DPass, "dpass", "dpass", false, false)
diff --git a/unittests/Support/CrashRecoveryTest.cpp b/unittests/Support/CrashRecoveryTest.cpp
index 33d87a1c0e4a..e9ffd1f8871f 100644
--- a/unittests/Support/CrashRecoveryTest.cpp
+++ b/unittests/Support/CrashRecoveryTest.cpp
@@ -17,10 +17,6 @@
#include <windows.h>
#endif
-extern "C" const char *__asan_default_options() {
- return "allow_user_segv_handler=1";
-}
-
using namespace llvm;
using namespace llvm::sys;