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