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 
TEST(WholeProgramDevirt,findLowestOffset)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 
TEST(WholeProgramDevirt,setReturnValues)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