diff options
Diffstat (limited to 'unittests')
-rw-r--r-- | unittests/ADT/APFloatTest.cpp | 275 | ||||
-rw-r--r-- | unittests/ADT/IntrusiveRefCntPtrTest.cpp | 4 | ||||
-rw-r--r-- | unittests/Bitcode/BitstreamReaderTest.cpp | 4 | ||||
-rw-r--r-- | unittests/DebugInfo/DWARF/DWARFDebugInfoTest.cpp | 121 | ||||
-rw-r--r-- | unittests/DebugInfo/DWARF/DwarfGenerator.cpp | 4 | ||||
-rw-r--r-- | unittests/DebugInfo/DWARF/DwarfGenerator.h | 3 |
6 files changed, 404 insertions, 7 deletions
diff --git a/unittests/ADT/APFloatTest.cpp b/unittests/ADT/APFloatTest.cpp index a273005cd1f3..83fb213109aa 100644 --- a/unittests/ADT/APFloatTest.cpp +++ b/unittests/ADT/APFloatTest.cpp @@ -1500,10 +1500,6 @@ TEST(APFloatTest, PPCDoubleDouble) { EXPECT_EQ(0x3ff0000000000000ull, test.bitcastToAPInt().getRawData()[0]); EXPECT_EQ(0x0000000000000000ull, test.bitcastToAPInt().getRawData()[1]); - test.divide(APFloat(APFloat::PPCDoubleDouble(), "3.0"), APFloat::rmNearestTiesToEven); - EXPECT_EQ(0x3fd5555555555555ull, test.bitcastToAPInt().getRawData()[0]); - EXPECT_EQ(0x3c75555555555556ull, test.bitcastToAPInt().getRawData()[1]); - // LDBL_MAX test = APFloat(APFloat::PPCDoubleDouble(), "1.79769313486231580793728971405301e+308"); EXPECT_EQ(0x7fefffffffffffffull, test.bitcastToAPInt().getRawData()[0]); @@ -3306,4 +3302,275 @@ TEST(APFloatTest, PPCDoubleDoubleSubtract) { .str(); } } + +TEST(APFloatTest, PPCDoubleDoubleMultiply) { + using DataType = std::tuple<uint64_t, uint64_t, uint64_t, uint64_t, uint64_t, + uint64_t, APFloat::roundingMode>; + // TODO: Only a sanity check for now. Add more edge cases when the + // double-double algorithm is implemented. + DataType Data[] = { + // 1/3 * 3 = 1.0 + std::make_tuple(0x3fd5555555555555ull, 0x3c75555555555556ull, + 0x4008000000000000ull, 0, 0x3ff0000000000000ull, 0, + APFloat::rmNearestTiesToEven), + }; + + for (auto Tp : Data) { + uint64_t Op1[2], Op2[2], Expected[2]; + APFloat::roundingMode RM; + std::tie(Op1[0], Op1[1], Op2[0], Op2[1], Expected[0], Expected[1], RM) = Tp; + + APFloat A1(APFloat::PPCDoubleDouble(), APInt(128, 2, Op1)); + APFloat A2(APFloat::PPCDoubleDouble(), APInt(128, 2, Op2)); + A1.multiply(A2, RM); + + EXPECT_EQ(Expected[0], A1.bitcastToAPInt().getRawData()[0]) + << formatv("({0:x} + {1:x}) * ({2:x} + {3:x})", Op1[0], Op1[1], Op2[0], + Op2[1]) + .str(); + EXPECT_EQ(Expected[1], A1.bitcastToAPInt().getRawData()[1]) + << formatv("({0:x} + {1:x}) * ({2:x} + {3:x})", Op1[0], Op1[1], Op2[0], + Op2[1]) + .str(); + } +} + +TEST(APFloatTest, PPCDoubleDoubleDivide) { + using DataType = std::tuple<uint64_t, uint64_t, uint64_t, uint64_t, uint64_t, + uint64_t, APFloat::roundingMode>; + // TODO: Only a sanity check for now. Add more edge cases when the + // double-double algorithm is implemented. + DataType Data[] = { + // 1 / 3 = 1/3 + std::make_tuple(0x3ff0000000000000ull, 0, 0x4008000000000000ull, 0, + 0x3fd5555555555555ull, 0x3c75555555555556ull, + APFloat::rmNearestTiesToEven), + }; + + for (auto Tp : Data) { + uint64_t Op1[2], Op2[2], Expected[2]; + APFloat::roundingMode RM; + std::tie(Op1[0], Op1[1], Op2[0], Op2[1], Expected[0], Expected[1], RM) = Tp; + + APFloat A1(APFloat::PPCDoubleDouble(), APInt(128, 2, Op1)); + APFloat A2(APFloat::PPCDoubleDouble(), APInt(128, 2, Op2)); + A1.divide(A2, RM); + + EXPECT_EQ(Expected[0], A1.bitcastToAPInt().getRawData()[0]) + << formatv("({0:x} + {1:x}) / ({2:x} + {3:x})", Op1[0], Op1[1], Op2[0], + Op2[1]) + .str(); + EXPECT_EQ(Expected[1], A1.bitcastToAPInt().getRawData()[1]) + << formatv("({0:x} + {1:x}) / ({2:x} + {3:x})", Op1[0], Op1[1], Op2[0], + Op2[1]) + .str(); + } +} + +TEST(APFloatTest, PPCDoubleDoubleRemainder) { + using DataType = + std::tuple<uint64_t, uint64_t, uint64_t, uint64_t, uint64_t, uint64_t>; + DataType Data[] = { + // remainder(3.0 + 3.0 << 53, 1.25 + 1.25 << 53) = (0.5 + 0.5 << 53) + std::make_tuple(0x4008000000000000ull, 0x3cb8000000000000ull, + 0x3ff4000000000000ull, 0x3ca4000000000000ull, + 0x3fe0000000000000ull, 0x3c90000000000000ull), + // remainder(3.0 + 3.0 << 53, 1.75 + 1.75 << 53) = (-0.5 - 0.5 << 53) + std::make_tuple(0x4008000000000000ull, 0x3cb8000000000000ull, + 0x3ffc000000000000ull, 0x3cac000000000000ull, + 0xbfe0000000000000ull, 0xbc90000000000000ull), + }; + + for (auto Tp : Data) { + uint64_t Op1[2], Op2[2], Expected[2]; + std::tie(Op1[0], Op1[1], Op2[0], Op2[1], Expected[0], Expected[1]) = Tp; + + APFloat A1(APFloat::PPCDoubleDouble(), APInt(128, 2, Op1)); + APFloat A2(APFloat::PPCDoubleDouble(), APInt(128, 2, Op2)); + A1.remainder(A2); + + EXPECT_EQ(Expected[0], A1.bitcastToAPInt().getRawData()[0]) + << formatv("remainder({0:x} + {1:x}), ({2:x} + {3:x}))", Op1[0], Op1[1], + Op2[0], Op2[1]) + .str(); + EXPECT_EQ(Expected[1], A1.bitcastToAPInt().getRawData()[1]) + << formatv("remainder(({0:x} + {1:x}), ({2:x} + {3:x}))", Op1[0], + Op1[1], Op2[0], Op2[1]) + .str(); + } +} + +TEST(APFloatTest, PPCDoubleDoubleMod) { + using DataType = + std::tuple<uint64_t, uint64_t, uint64_t, uint64_t, uint64_t, uint64_t>; + DataType Data[] = { + // mod(3.0 + 3.0 << 53, 1.25 + 1.25 << 53) = (0.5 + 0.5 << 53) + std::make_tuple(0x4008000000000000ull, 0x3cb8000000000000ull, + 0x3ff4000000000000ull, 0x3ca4000000000000ull, + 0x3fe0000000000000ull, 0x3c90000000000000ull), + // mod(3.0 + 3.0 << 53, 1.75 + 1.75 << 53) = (1.25 + 1.25 << 53) + // 0xbc98000000000000 doesn't seem right, but it's what we currently have. + // TODO: investigate + std::make_tuple(0x4008000000000000ull, 0x3cb8000000000000ull, + 0x3ffc000000000000ull, 0x3cac000000000000ull, + 0x3ff4000000000001ull, 0xbc98000000000000ull), + }; + + for (auto Tp : Data) { + uint64_t Op1[2], Op2[2], Expected[2]; + std::tie(Op1[0], Op1[1], Op2[0], Op2[1], Expected[0], Expected[1]) = Tp; + + APFloat A1(APFloat::PPCDoubleDouble(), APInt(128, 2, Op1)); + APFloat A2(APFloat::PPCDoubleDouble(), APInt(128, 2, Op2)); + A1.mod(A2); + + EXPECT_EQ(Expected[0], A1.bitcastToAPInt().getRawData()[0]) + << formatv("fmod(({0:x} + {1:x}), ({2:x} + {3:x}))", Op1[0], Op1[1], + Op2[0], Op2[1]) + .str(); + EXPECT_EQ(Expected[1], A1.bitcastToAPInt().getRawData()[1]) + << formatv("fmod(({0:x} + {1:x}), ({2:x} + {3:x}))", Op1[0], Op1[1], + Op2[0], Op2[1]) + .str(); + } +} + +TEST(APFloatTest, PPCDoubleDoubleFMA) { + // Sanity check for now. + APFloat A(APFloat::PPCDoubleDouble(), "2"); + A.fusedMultiplyAdd(APFloat(APFloat::PPCDoubleDouble(), "3"), + APFloat(APFloat::PPCDoubleDouble(), "4"), + APFloat::rmNearestTiesToEven); + EXPECT_EQ(APFloat::cmpEqual, + APFloat(APFloat::PPCDoubleDouble(), "10").compare(A)); +} + +TEST(APFloatTest, PPCDoubleDoubleRoundToIntegral) { + { + APFloat A(APFloat::PPCDoubleDouble(), "1.5"); + A.roundToIntegral(APFloat::rmNearestTiesToEven); + EXPECT_EQ(APFloat::cmpEqual, + APFloat(APFloat::PPCDoubleDouble(), "2").compare(A)); + } + { + APFloat A(APFloat::PPCDoubleDouble(), "2.5"); + A.roundToIntegral(APFloat::rmNearestTiesToEven); + EXPECT_EQ(APFloat::cmpEqual, + APFloat(APFloat::PPCDoubleDouble(), "2").compare(A)); + } +} + +TEST(APFloatTest, PPCDoubleDoubleCompare) { + using DataType = + std::tuple<uint64_t, uint64_t, uint64_t, uint64_t, APFloat::cmpResult>; + + DataType Data[] = { + // (1 + 0) = (1 + 0) + std::make_tuple(0x3ff0000000000000ull, 0, 0x3ff0000000000000ull, 0, + APFloat::cmpEqual), + // (1 + 0) < (1.00...1 + 0) + std::make_tuple(0x3ff0000000000000ull, 0, 0x3ff0000000000001ull, 0, + APFloat::cmpLessThan), + // (1.00...1 + 0) > (1 + 0) + std::make_tuple(0x3ff0000000000001ull, 0, 0x3ff0000000000000ull, 0, + APFloat::cmpGreaterThan), + // (1 + 0) < (1 + epsilon) + std::make_tuple(0x3ff0000000000000ull, 0, 0x3ff0000000000001ull, + 0x0000000000000001ull, APFloat::cmpLessThan), + // NaN != NaN + std::make_tuple(0x7ff8000000000000ull, 0, 0x7ff8000000000000ull, 0, + APFloat::cmpUnordered), + // (1 + 0) != NaN + std::make_tuple(0x3ff0000000000000ull, 0, 0x7ff8000000000000ull, 0, + APFloat::cmpUnordered), + // Inf = Inf + std::make_tuple(0x7ff0000000000000ull, 0, 0x7ff0000000000000ull, 0, + APFloat::cmpEqual), + }; + + for (auto Tp : Data) { + uint64_t Op1[2], Op2[2]; + APFloat::cmpResult Expected; + std::tie(Op1[0], Op1[1], Op2[0], Op2[1], Expected) = Tp; + + APFloat A1(APFloat::PPCDoubleDouble(), APInt(128, 2, Op1)); + APFloat A2(APFloat::PPCDoubleDouble(), APInt(128, 2, Op2)); + EXPECT_EQ(Expected, A1.compare(A2)) + << formatv("({0:x} + {1:x}) - ({2:x} + {3:x})", Op1[0], Op1[1], Op2[0], + Op2[1]) + .str(); + } +} + +TEST(APFloatTest, PPCDoubleDoubleChangeSign) { + uint64_t Data[] = { + 0x400f000000000000ull, 0xbcb0000000000000ull, + }; + APFloat Float(APFloat::PPCDoubleDouble(), APInt(128, 2, Data)); + { + APFloat Actual = + APFloat::copySign(Float, APFloat(APFloat::IEEEdouble(), "1")); + EXPECT_EQ(0x400f000000000000ull, Actual.bitcastToAPInt().getRawData()[0]); + EXPECT_EQ(0xbcb0000000000000ull, Actual.bitcastToAPInt().getRawData()[1]); + } + { + APFloat Actual = + APFloat::copySign(Float, APFloat(APFloat::IEEEdouble(), "-1")); + EXPECT_EQ(0xc00f000000000000ull, Actual.bitcastToAPInt().getRawData()[0]); + EXPECT_EQ(0x3cb0000000000000ull, Actual.bitcastToAPInt().getRawData()[1]); + } +} + +TEST(APFloatTest, PPCDoubleDoubleFactories) { + { + uint64_t Data[] = { + 0, 0, + }; + EXPECT_EQ(APInt(128, 2, Data), + APFloat::getZero(APFloat::PPCDoubleDouble()).bitcastToAPInt()); + } + { + uint64_t Data[] = { + 0x0000000000000001ull, 0, + }; + EXPECT_EQ( + APInt(128, 2, Data), + APFloat::getSmallest(APFloat::PPCDoubleDouble()).bitcastToAPInt()); + } + { + uint64_t Data[] = {0x0360000000000000ull, 0}; + EXPECT_EQ(APInt(128, 2, Data), + APFloat::getSmallestNormalized(APFloat::PPCDoubleDouble()) + .bitcastToAPInt()); + } + { + uint64_t Data[] = { + 0x8000000000000000ull, 0x0000000000000000ull, + }; + EXPECT_EQ( + APInt(128, 2, Data), + APFloat::getZero(APFloat::PPCDoubleDouble(), true).bitcastToAPInt()); + } + { + uint64_t Data[] = { + 0x8000000000000001ull, 0x0000000000000000ull, + }; + EXPECT_EQ(APInt(128, 2, Data), + APFloat::getSmallest(APFloat::PPCDoubleDouble(), true) + .bitcastToAPInt()); + } + + EXPECT_EQ(0x8360000000000000ull, + APFloat::getSmallestNormalized(APFloat::PPCDoubleDouble(), true) + .bitcastToAPInt() + .getRawData()[0]); + EXPECT_EQ(0x0000000000000000ull, + APFloat::getSmallestNormalized(APFloat::PPCDoubleDouble(), true) + .getSecondFloat() + .bitcastToAPInt() + .getRawData()[0]); + + EXPECT_TRUE(APFloat::getSmallest(APFloat::PPCDoubleDouble()).isSmallest()); + EXPECT_TRUE(APFloat::getLargest(APFloat::PPCDoubleDouble()).isLargest()); +} } diff --git a/unittests/ADT/IntrusiveRefCntPtrTest.cpp b/unittests/ADT/IntrusiveRefCntPtrTest.cpp index 143a8cc49107..83dc13766497 100644 --- a/unittests/ADT/IntrusiveRefCntPtrTest.cpp +++ b/unittests/ADT/IntrusiveRefCntPtrTest.cpp @@ -15,7 +15,9 @@ namespace llvm { namespace { struct SimpleRefCounted : public RefCountedBase<SimpleRefCounted> { SimpleRefCounted() { ++NumInstances; } - SimpleRefCounted(const SimpleRefCounted &) { ++NumInstances; } + SimpleRefCounted(const SimpleRefCounted &) : RefCountedBase() { + ++NumInstances; + } ~SimpleRefCounted() { --NumInstances; } static int NumInstances; diff --git a/unittests/Bitcode/BitstreamReaderTest.cpp b/unittests/Bitcode/BitstreamReaderTest.cpp index 704eb803f9c7..935ef4bcffc0 100644 --- a/unittests/Bitcode/BitstreamReaderTest.cpp +++ b/unittests/Bitcode/BitstreamReaderTest.cpp @@ -101,10 +101,10 @@ TEST(BitstreamReaderTest, readRecordWithBlobWhileStreaming) { Stream.Emit(Magic, 32); Stream.EnterSubblock(BlockID, 3); - BitCodeAbbrev *Abbrev = new BitCodeAbbrev(); + auto Abbrev = std::make_shared<BitCodeAbbrev>(); Abbrev->Add(BitCodeAbbrevOp(RecordID)); Abbrev->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Blob)); - AbbrevID = Stream.EmitAbbrev(Abbrev); + AbbrevID = Stream.EmitAbbrev(std::move(Abbrev)); unsigned Record[] = {RecordID}; Stream.EmitRecordWithBlob(AbbrevID, makeArrayRef(Record), BlobIn); diff --git a/unittests/DebugInfo/DWARF/DWARFDebugInfoTest.cpp b/unittests/DebugInfo/DWARF/DWARFDebugInfoTest.cpp index ec8297f277f4..4435b7942682 100644 --- a/unittests/DebugInfo/DWARF/DWARFDebugInfoTest.cpp +++ b/unittests/DebugInfo/DWARF/DWARFDebugInfoTest.cpp @@ -1100,5 +1100,126 @@ TEST(DWARFDebugInfo, TestDWARFDie) { EXPECT_FALSE(DefaultDie.getSibling().isValid()); } +TEST(DWARFDebugInfo, TestChildIterators) { + // Test the DWARF APIs related to iterating across the children of a DIE using + // the DWARFDie::iterator class. + uint16_t Version = 4; + + const uint8_t AddrSize = sizeof(void *); + initLLVMIfNeeded(); + Triple Triple = getHostTripleForAddrSize(AddrSize); + auto ExpectedDG = dwarfgen::Generator::create(Triple, Version); + if (HandleExpectedError(ExpectedDG)) + return; + dwarfgen::Generator *DG = ExpectedDG.get().get(); + dwarfgen::CompileUnit &CU = DG->addCompileUnit(); + + enum class Tag: uint16_t { + A = dwarf::DW_TAG_lo_user, + B, + }; + + // Scope to allow us to re-use the same DIE names + { + // Create DWARF tree that looks like: + // + // CU + // A + // B + auto CUDie = CU.getUnitDIE(); + CUDie.addChild((dwarf::Tag)Tag::A); + CUDie.addChild((dwarf::Tag)Tag::B); + } + + MemoryBufferRef FileBuffer(DG->generate(), "dwarf"); + auto Obj = object::ObjectFile::createObjectFile(FileBuffer); + EXPECT_TRUE((bool)Obj); + DWARFContextInMemory DwarfContext(*Obj.get()); + + // Verify the number of compile units is correct. + uint32_t NumCUs = DwarfContext.getNumCompileUnits(); + EXPECT_EQ(NumCUs, 1u); + DWARFCompileUnit *U = DwarfContext.getCompileUnitAtIndex(0); + + // Get the compile unit DIE is valid. + auto CUDie = U->getUnitDIE(false); + EXPECT_TRUE(CUDie.isValid()); + // CUDie.dump(llvm::outs(), UINT32_MAX); + uint32_t Index; + DWARFDie A; + DWARFDie B; + + // Verify the compile unit DIE's children. + Index = 0; + for (auto Die : CUDie.children()) { + switch (Index++) { + case 0: A = Die; break; + case 1: B = Die; break; + } + } + + EXPECT_EQ(A.getTag(), (dwarf::Tag)Tag::A); + EXPECT_EQ(B.getTag(), (dwarf::Tag)Tag::B); + + // Verify that A has no children by verifying that the begin and end contain + // invalid DIEs and also that the iterators are equal. + EXPECT_EQ(A.begin(), A.end()); +} + +TEST(DWARFDebugInfo, TestChildIteratorsOnInvalidDie) { + // Verify that an invalid DIE has no children. + DWARFDie Invalid; + auto begin = Invalid.begin(); + auto end = Invalid.end(); + EXPECT_FALSE(begin->isValid()); + EXPECT_FALSE(end->isValid()); + EXPECT_EQ(begin, end); +} + + +TEST(DWARFDebugInfo, TestEmptyChildren) { + // Test a DIE that says it has children in the abbreviation, but actually + // doesn't have any attributes, will not return anything during iteration. + // We do this by making sure the begin and end iterators are equal. + uint16_t Version = 4; + + const uint8_t AddrSize = sizeof(void *); + initLLVMIfNeeded(); + Triple Triple = getHostTripleForAddrSize(AddrSize); + auto ExpectedDG = dwarfgen::Generator::create(Triple, Version); + if (HandleExpectedError(ExpectedDG)) + return; + dwarfgen::Generator *DG = ExpectedDG.get().get(); + dwarfgen::CompileUnit &CU = DG->addCompileUnit(); + + // Scope to allow us to re-use the same DIE names + { + // Create a compile unit DIE that has an abbreviation that says it has + // children, but doesn't have any actual attributes. This helps us test + // a DIE that has only one child: a NULL DIE. + auto CUDie = CU.getUnitDIE(); + CUDie.setForceChildren(); + } + + MemoryBufferRef FileBuffer(DG->generate(), "dwarf"); + auto Obj = object::ObjectFile::createObjectFile(FileBuffer); + EXPECT_TRUE((bool)Obj); + DWARFContextInMemory DwarfContext(*Obj.get()); + + // Verify the number of compile units is correct. + uint32_t NumCUs = DwarfContext.getNumCompileUnits(); + EXPECT_EQ(NumCUs, 1u); + DWARFCompileUnit *U = DwarfContext.getCompileUnitAtIndex(0); + + // Get the compile unit DIE is valid. + auto CUDie = U->getUnitDIE(false); + EXPECT_TRUE(CUDie.isValid()); + CUDie.dump(llvm::outs(), UINT32_MAX); + + // Verify that the CU Die that says it has children, but doesn't, actually + // has begin and end iterators that are equal. We want to make sure we don't + // see the Null DIEs during iteration. + EXPECT_EQ(CUDie.begin(), CUDie.end()); +} } // end anonymous namespace diff --git a/unittests/DebugInfo/DWARF/DwarfGenerator.cpp b/unittests/DebugInfo/DWARF/DwarfGenerator.cpp index 9a72f70a0f21..9ec43cab4dc0 100644 --- a/unittests/DebugInfo/DWARF/DwarfGenerator.cpp +++ b/unittests/DebugInfo/DWARF/DwarfGenerator.cpp @@ -108,6 +108,10 @@ dwarfgen::DIE dwarfgen::CompileUnit::getUnitDIE() { return dwarfgen::DIE(this, &DU.getUnitDie()); } +void dwarfgen::DIE::setForceChildren() { + Die->setForceChildren(true); +} + //===----------------------------------------------------------------------===// /// dwarfgen::Generator implementation. //===----------------------------------------------------------------------===// diff --git a/unittests/DebugInfo/DWARF/DwarfGenerator.h b/unittests/DebugInfo/DWARF/DwarfGenerator.h index 966725b4fa4e..2978d1ca0021 100644 --- a/unittests/DebugInfo/DWARF/DwarfGenerator.h +++ b/unittests/DebugInfo/DWARF/DwarfGenerator.h @@ -129,6 +129,9 @@ public: /// \returns the newly created DIE object that is now a child owned by this /// object. dwarfgen::DIE addChild(dwarf::Tag Tag); + + /// Force a DIE to say it has children even when it doesn't. + void setForceChildren(); }; /// A DWARF compile unit used to generate DWARF compile/type units. |