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