blob: 7e7a6bf459641037a270f2b18cfb95fd41ccebe1 [file] [log] [blame]
Peter Collingbournedf49d1b2016-02-09 22:50:34 +00001//===- 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"
Mehdi Aminib550cb12016-04-18 09:17:29 +000011#include "llvm/ADT/ArrayRef.h"
Peter Collingbournedf49d1b2016-02-09 22:50:34 +000012#include "gtest/gtest.h"
13
14using namespace llvm;
15using namespace wholeprogramdevirt;
16
17TEST(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
Peter Collingbourne7efd7502016-06-24 21:21:32 +000028 TypeMemberInfo TM1{&VT1, 0};
29 TypeMemberInfo TM2{&VT2, 0};
Peter Collingbournedf49d1b2016-02-09 22:50:34 +000030 VirtualCallTarget Targets[] = {
Peter Collingbourne7efd7502016-06-24 21:21:32 +000031 {&TM1, /*IsBigEndian=*/false},
32 {&TM2, /*IsBigEndian=*/false},
Peter Collingbournedf49d1b2016-02-09 22:50:34 +000033 };
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
Peter Collingbourne7efd7502016-06-24 21:21:32 +000041 TM1.Offset = 4;
Peter Collingbournedf49d1b2016-02-09 22:50:34 +000042 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
Peter Collingbourne7efd7502016-06-24 21:21:32 +000048 TM1.Offset = 8;
49 TM2.Offset = 8;
Peter Collingbournedf49d1b2016-02-09 22:50:34 +000050 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
62TEST(WholeProgramDevirt, setReturnValues) {
63 VTableBits VT1;
64 VT1.ObjectSize = 8;
65
66 VTableBits VT2;
67 VT2.ObjectSize = 8;
68
Peter Collingbourne7efd7502016-06-24 21:21:32 +000069 TypeMemberInfo TM1{&VT1, 0};
70 TypeMemberInfo TM2{&VT2, 0};
Peter Collingbournedf49d1b2016-02-09 22:50:34 +000071 VirtualCallTarget Targets[] = {
Peter Collingbourne7efd7502016-06-24 21:21:32 +000072 {&TM1, /*IsBigEndian=*/false},
73 {&TM2, /*IsBigEndian=*/false},
Peter Collingbournedf49d1b2016-02-09 22:50:34 +000074 };
75
Peter Collingbourne7efd7502016-06-24 21:21:32 +000076 TM1.Offset = 4;
77 TM2.Offset = 4;
Peter Collingbournedf49d1b2016-02-09 22:50:34 +000078
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}