1 //===- WholeProgramDevirt.cpp - Unit tests for whole-program devirt -------===//
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
7 //===----------------------------------------------------------------------===//
9 #include "llvm/Transforms/IPO/WholeProgramDevirt.h"
10 #include "llvm/ADT/ArrayRef.h"
11 #include "gtest/gtest.h"
14 using namespace wholeprogramdevirt
;
16 TEST(WholeProgramDevirt
, findLowestOffset
) {
19 VT1
.Before
.BytesUsed
= {1 << 0};
20 VT1
.After
.BytesUsed
= {1 << 1};
24 VT2
.Before
.BytesUsed
= {1 << 1};
25 VT2
.After
.BytesUsed
= {1 << 0};
27 TypeMemberInfo TM1
{&VT1
, 0};
28 TypeMemberInfo TM2
{&VT2
, 0};
29 VirtualCallTarget Targets
[] = {
30 {&TM1
, /*IsBigEndian=*/false},
31 {&TM2
, /*IsBigEndian=*/false},
34 EXPECT_EQ(2ull, findLowestOffset(Targets
, /*IsAfter=*/false, 1));
35 EXPECT_EQ(66ull, findLowestOffset(Targets
, /*IsAfter=*/true, 1));
37 EXPECT_EQ(8ull, findLowestOffset(Targets
, /*IsAfter=*/false, 8));
38 EXPECT_EQ(72ull, findLowestOffset(Targets
, /*IsAfter=*/true, 8));
41 EXPECT_EQ(33ull, findLowestOffset(Targets
, /*IsAfter=*/false, 1));
42 EXPECT_EQ(65ull, findLowestOffset(Targets
, /*IsAfter=*/true, 1));
44 EXPECT_EQ(40ull, findLowestOffset(Targets
, /*IsAfter=*/false, 8));
45 EXPECT_EQ(72ull, findLowestOffset(Targets
, /*IsAfter=*/true, 8));
49 EXPECT_EQ(66ull, findLowestOffset(Targets
, /*IsAfter=*/false, 1));
50 EXPECT_EQ(2ull, findLowestOffset(Targets
, /*IsAfter=*/true, 1));
52 EXPECT_EQ(72ull, findLowestOffset(Targets
, /*IsAfter=*/false, 8));
53 EXPECT_EQ(8ull, findLowestOffset(Targets
, /*IsAfter=*/true, 8));
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));
61 TEST(WholeProgramDevirt
, setReturnValues
) {
68 TypeMemberInfo TM1
{&VT1
, 0};
69 TypeMemberInfo TM2
{&VT2
, 0};
70 VirtualCallTarget Targets
[] = {
71 {&TM1
, /*IsBigEndian=*/false},
72 {&TM2
, /*IsBigEndian=*/false},
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
);
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
);
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
);
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
);
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
);
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
);
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
);
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
);