1df49d1bbSPeter Collingbourne //===- WholeProgramDevirt.cpp - Unit tests for whole-program devirt -------===// 2df49d1bbSPeter Collingbourne // 3df49d1bbSPeter Collingbourne // The LLVM Compiler Infrastructure 4df49d1bbSPeter Collingbourne // 5df49d1bbSPeter Collingbourne // This file is distributed under the University of Illinois Open Source 6df49d1bbSPeter Collingbourne // License. See LICENSE.TXT for details. 7df49d1bbSPeter Collingbourne // 8df49d1bbSPeter Collingbourne //===----------------------------------------------------------------------===// 9df49d1bbSPeter Collingbourne 10df49d1bbSPeter Collingbourne #include "llvm/Transforms/IPO/WholeProgramDevirt.h" 11b550cb17SMehdi Amini #include "llvm/ADT/ArrayRef.h" 12df49d1bbSPeter Collingbourne #include "gtest/gtest.h" 13df49d1bbSPeter Collingbourne 14df49d1bbSPeter Collingbourne using namespace llvm; 15df49d1bbSPeter Collingbourne using namespace wholeprogramdevirt; 16df49d1bbSPeter Collingbourne 17df49d1bbSPeter Collingbourne TEST(WholeProgramDevirt, findLowestOffset) { 18df49d1bbSPeter Collingbourne VTableBits VT1; 19df49d1bbSPeter Collingbourne VT1.ObjectSize = 8; 20df49d1bbSPeter Collingbourne VT1.Before.BytesUsed = {1 << 0}; 21df49d1bbSPeter Collingbourne VT1.After.BytesUsed = {1 << 1}; 22df49d1bbSPeter Collingbourne 23df49d1bbSPeter Collingbourne VTableBits VT2; 24df49d1bbSPeter Collingbourne VT2.ObjectSize = 8; 25df49d1bbSPeter Collingbourne VT2.Before.BytesUsed = {1 << 1}; 26df49d1bbSPeter Collingbourne VT2.After.BytesUsed = {1 << 0}; 27df49d1bbSPeter Collingbourne 28*7efd7506SPeter Collingbourne TypeMemberInfo TM1{&VT1, 0}; 29*7efd7506SPeter Collingbourne TypeMemberInfo TM2{&VT2, 0}; 30df49d1bbSPeter Collingbourne VirtualCallTarget Targets[] = { 31*7efd7506SPeter Collingbourne {&TM1, /*IsBigEndian=*/false}, 32*7efd7506SPeter Collingbourne {&TM2, /*IsBigEndian=*/false}, 33df49d1bbSPeter Collingbourne }; 34df49d1bbSPeter Collingbourne 35df49d1bbSPeter Collingbourne EXPECT_EQ(2ull, findLowestOffset(Targets, /*IsAfter=*/false, 1)); 36df49d1bbSPeter Collingbourne EXPECT_EQ(66ull, findLowestOffset(Targets, /*IsAfter=*/true, 1)); 37df49d1bbSPeter Collingbourne 38df49d1bbSPeter Collingbourne EXPECT_EQ(8ull, findLowestOffset(Targets, /*IsAfter=*/false, 8)); 39df49d1bbSPeter Collingbourne EXPECT_EQ(72ull, findLowestOffset(Targets, /*IsAfter=*/true, 8)); 40df49d1bbSPeter Collingbourne 41*7efd7506SPeter Collingbourne TM1.Offset = 4; 42df49d1bbSPeter Collingbourne EXPECT_EQ(33ull, findLowestOffset(Targets, /*IsAfter=*/false, 1)); 43df49d1bbSPeter Collingbourne EXPECT_EQ(65ull, findLowestOffset(Targets, /*IsAfter=*/true, 1)); 44df49d1bbSPeter Collingbourne 45df49d1bbSPeter Collingbourne EXPECT_EQ(40ull, findLowestOffset(Targets, /*IsAfter=*/false, 8)); 46df49d1bbSPeter Collingbourne EXPECT_EQ(72ull, findLowestOffset(Targets, /*IsAfter=*/true, 8)); 47df49d1bbSPeter Collingbourne 48*7efd7506SPeter Collingbourne TM1.Offset = 8; 49*7efd7506SPeter Collingbourne TM2.Offset = 8; 50df49d1bbSPeter Collingbourne EXPECT_EQ(66ull, findLowestOffset(Targets, /*IsAfter=*/false, 1)); 51df49d1bbSPeter Collingbourne EXPECT_EQ(2ull, findLowestOffset(Targets, /*IsAfter=*/true, 1)); 52df49d1bbSPeter Collingbourne 53df49d1bbSPeter Collingbourne EXPECT_EQ(72ull, findLowestOffset(Targets, /*IsAfter=*/false, 8)); 54df49d1bbSPeter Collingbourne EXPECT_EQ(8ull, findLowestOffset(Targets, /*IsAfter=*/true, 8)); 55df49d1bbSPeter Collingbourne 56df49d1bbSPeter Collingbourne VT1.After.BytesUsed = {0xff, 0, 0, 0, 0xff}; 57df49d1bbSPeter Collingbourne VT2.After.BytesUsed = {0xff, 1, 0, 0, 0}; 58df49d1bbSPeter Collingbourne EXPECT_EQ(16ull, findLowestOffset(Targets, /*IsAfter=*/true, 16)); 59df49d1bbSPeter Collingbourne EXPECT_EQ(40ull, findLowestOffset(Targets, /*IsAfter=*/true, 32)); 60df49d1bbSPeter Collingbourne } 61df49d1bbSPeter Collingbourne 62df49d1bbSPeter Collingbourne TEST(WholeProgramDevirt, setReturnValues) { 63df49d1bbSPeter Collingbourne VTableBits VT1; 64df49d1bbSPeter Collingbourne VT1.ObjectSize = 8; 65df49d1bbSPeter Collingbourne 66df49d1bbSPeter Collingbourne VTableBits VT2; 67df49d1bbSPeter Collingbourne VT2.ObjectSize = 8; 68df49d1bbSPeter Collingbourne 69*7efd7506SPeter Collingbourne TypeMemberInfo TM1{&VT1, 0}; 70*7efd7506SPeter Collingbourne TypeMemberInfo TM2{&VT2, 0}; 71df49d1bbSPeter Collingbourne VirtualCallTarget Targets[] = { 72*7efd7506SPeter Collingbourne {&TM1, /*IsBigEndian=*/false}, 73*7efd7506SPeter Collingbourne {&TM2, /*IsBigEndian=*/false}, 74df49d1bbSPeter Collingbourne }; 75df49d1bbSPeter Collingbourne 76*7efd7506SPeter Collingbourne TM1.Offset = 4; 77*7efd7506SPeter Collingbourne TM2.Offset = 4; 78df49d1bbSPeter Collingbourne 79df49d1bbSPeter Collingbourne int64_t OffsetByte; 80df49d1bbSPeter Collingbourne uint64_t OffsetBit; 81df49d1bbSPeter Collingbourne 82df49d1bbSPeter Collingbourne Targets[0].RetVal = 1; 83df49d1bbSPeter Collingbourne Targets[1].RetVal = 0; 84df49d1bbSPeter Collingbourne setBeforeReturnValues(Targets, 32, 1, OffsetByte, OffsetBit); 85df49d1bbSPeter Collingbourne EXPECT_EQ(-5ll, OffsetByte); 86df49d1bbSPeter Collingbourne EXPECT_EQ(0ull, OffsetBit); 87df49d1bbSPeter Collingbourne EXPECT_EQ(std::vector<uint8_t>{1}, VT1.Before.Bytes); 88df49d1bbSPeter Collingbourne EXPECT_EQ(std::vector<uint8_t>{1}, VT1.Before.BytesUsed); 89df49d1bbSPeter Collingbourne EXPECT_EQ(std::vector<uint8_t>{0}, VT2.Before.Bytes); 90df49d1bbSPeter Collingbourne EXPECT_EQ(std::vector<uint8_t>{1}, VT2.Before.BytesUsed); 91df49d1bbSPeter Collingbourne 92df49d1bbSPeter Collingbourne Targets[0].RetVal = 0; 93df49d1bbSPeter Collingbourne Targets[1].RetVal = 1; 94df49d1bbSPeter Collingbourne setBeforeReturnValues(Targets, 39, 1, OffsetByte, OffsetBit); 95df49d1bbSPeter Collingbourne EXPECT_EQ(-5ll, OffsetByte); 96df49d1bbSPeter Collingbourne EXPECT_EQ(7ull, OffsetBit); 97df49d1bbSPeter Collingbourne EXPECT_EQ(std::vector<uint8_t>{1}, VT1.Before.Bytes); 98df49d1bbSPeter Collingbourne EXPECT_EQ(std::vector<uint8_t>{0x81}, VT1.Before.BytesUsed); 99df49d1bbSPeter Collingbourne EXPECT_EQ(std::vector<uint8_t>{0x80}, VT2.Before.Bytes); 100df49d1bbSPeter Collingbourne EXPECT_EQ(std::vector<uint8_t>{0x81}, VT2.Before.BytesUsed); 101df49d1bbSPeter Collingbourne 102df49d1bbSPeter Collingbourne Targets[0].RetVal = 12; 103df49d1bbSPeter Collingbourne Targets[1].RetVal = 34; 104df49d1bbSPeter Collingbourne setBeforeReturnValues(Targets, 40, 8, OffsetByte, OffsetBit); 105df49d1bbSPeter Collingbourne EXPECT_EQ(-6ll, OffsetByte); 106df49d1bbSPeter Collingbourne EXPECT_EQ(0ull, OffsetBit); 107df49d1bbSPeter Collingbourne EXPECT_EQ((std::vector<uint8_t>{1, 12}), VT1.Before.Bytes); 108df49d1bbSPeter Collingbourne EXPECT_EQ((std::vector<uint8_t>{0x81, 0xff}), VT1.Before.BytesUsed); 109df49d1bbSPeter Collingbourne EXPECT_EQ((std::vector<uint8_t>{0x80, 34}), VT2.Before.Bytes); 110df49d1bbSPeter Collingbourne EXPECT_EQ((std::vector<uint8_t>{0x81, 0xff}), VT2.Before.BytesUsed); 111df49d1bbSPeter Collingbourne 112df49d1bbSPeter Collingbourne Targets[0].RetVal = 56; 113df49d1bbSPeter Collingbourne Targets[1].RetVal = 78; 114df49d1bbSPeter Collingbourne setBeforeReturnValues(Targets, 48, 16, OffsetByte, OffsetBit); 115df49d1bbSPeter Collingbourne EXPECT_EQ(-8ll, OffsetByte); 116df49d1bbSPeter Collingbourne EXPECT_EQ(0ull, OffsetBit); 117df49d1bbSPeter Collingbourne EXPECT_EQ((std::vector<uint8_t>{1, 12, 0, 56}), VT1.Before.Bytes); 118df49d1bbSPeter Collingbourne EXPECT_EQ((std::vector<uint8_t>{0x81, 0xff, 0xff, 0xff}), 119df49d1bbSPeter Collingbourne VT1.Before.BytesUsed); 120df49d1bbSPeter Collingbourne EXPECT_EQ((std::vector<uint8_t>{0x80, 34, 0, 78}), VT2.Before.Bytes); 121df49d1bbSPeter Collingbourne EXPECT_EQ((std::vector<uint8_t>{0x81, 0xff, 0xff, 0xff}), 122df49d1bbSPeter Collingbourne VT2.Before.BytesUsed); 123df49d1bbSPeter Collingbourne 124df49d1bbSPeter Collingbourne Targets[0].RetVal = 1; 125df49d1bbSPeter Collingbourne Targets[1].RetVal = 0; 126df49d1bbSPeter Collingbourne setAfterReturnValues(Targets, 32, 1, OffsetByte, OffsetBit); 127df49d1bbSPeter Collingbourne EXPECT_EQ(4ll, OffsetByte); 128df49d1bbSPeter Collingbourne EXPECT_EQ(0ull, OffsetBit); 129df49d1bbSPeter Collingbourne EXPECT_EQ(std::vector<uint8_t>{1}, VT1.After.Bytes); 130df49d1bbSPeter Collingbourne EXPECT_EQ(std::vector<uint8_t>{1}, VT1.After.BytesUsed); 131df49d1bbSPeter Collingbourne EXPECT_EQ(std::vector<uint8_t>{0}, VT2.After.Bytes); 132df49d1bbSPeter Collingbourne EXPECT_EQ(std::vector<uint8_t>{1}, VT2.After.BytesUsed); 133df49d1bbSPeter Collingbourne 134df49d1bbSPeter Collingbourne Targets[0].RetVal = 0; 135df49d1bbSPeter Collingbourne Targets[1].RetVal = 1; 136df49d1bbSPeter Collingbourne setAfterReturnValues(Targets, 39, 1, OffsetByte, OffsetBit); 137df49d1bbSPeter Collingbourne EXPECT_EQ(4ll, OffsetByte); 138df49d1bbSPeter Collingbourne EXPECT_EQ(7ull, OffsetBit); 139df49d1bbSPeter Collingbourne EXPECT_EQ(std::vector<uint8_t>{1}, VT1.After.Bytes); 140df49d1bbSPeter Collingbourne EXPECT_EQ(std::vector<uint8_t>{0x81}, VT1.After.BytesUsed); 141df49d1bbSPeter Collingbourne EXPECT_EQ(std::vector<uint8_t>{0x80}, VT2.After.Bytes); 142df49d1bbSPeter Collingbourne EXPECT_EQ(std::vector<uint8_t>{0x81}, VT2.After.BytesUsed); 143df49d1bbSPeter Collingbourne 144df49d1bbSPeter Collingbourne Targets[0].RetVal = 12; 145df49d1bbSPeter Collingbourne Targets[1].RetVal = 34; 146df49d1bbSPeter Collingbourne setAfterReturnValues(Targets, 40, 8, OffsetByte, OffsetBit); 147df49d1bbSPeter Collingbourne EXPECT_EQ(5ll, OffsetByte); 148df49d1bbSPeter Collingbourne EXPECT_EQ(0ull, OffsetBit); 149df49d1bbSPeter Collingbourne EXPECT_EQ((std::vector<uint8_t>{1, 12}), VT1.After.Bytes); 150df49d1bbSPeter Collingbourne EXPECT_EQ((std::vector<uint8_t>{0x81, 0xff}), VT1.After.BytesUsed); 151df49d1bbSPeter Collingbourne EXPECT_EQ((std::vector<uint8_t>{0x80, 34}), VT2.After.Bytes); 152df49d1bbSPeter Collingbourne EXPECT_EQ((std::vector<uint8_t>{0x81, 0xff}), VT2.After.BytesUsed); 153df49d1bbSPeter Collingbourne 154df49d1bbSPeter Collingbourne Targets[0].RetVal = 56; 155df49d1bbSPeter Collingbourne Targets[1].RetVal = 78; 156df49d1bbSPeter Collingbourne setAfterReturnValues(Targets, 48, 16, OffsetByte, OffsetBit); 157df49d1bbSPeter Collingbourne EXPECT_EQ(6ll, OffsetByte); 158df49d1bbSPeter Collingbourne EXPECT_EQ(0ull, OffsetBit); 159df49d1bbSPeter Collingbourne EXPECT_EQ((std::vector<uint8_t>{1, 12, 56, 0}), VT1.After.Bytes); 160df49d1bbSPeter Collingbourne EXPECT_EQ((std::vector<uint8_t>{0x81, 0xff, 0xff, 0xff}), 161df49d1bbSPeter Collingbourne VT1.After.BytesUsed); 162df49d1bbSPeter Collingbourne EXPECT_EQ((std::vector<uint8_t>{0x80, 34, 78, 0}), VT2.After.Bytes); 163df49d1bbSPeter Collingbourne EXPECT_EQ((std::vector<uint8_t>{0x81, 0xff, 0xff, 0xff}), 164df49d1bbSPeter Collingbourne VT2.After.BytesUsed); 165df49d1bbSPeter Collingbourne } 166