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