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