1 //===- 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"
11 #include "llvm/ADT/ArrayRef.h"
12 #include "gtest/gtest.h"
13 
14 using namespace llvm;
15 using namespace wholeprogramdevirt;
16 
TEST(WholeProgramDevirt,findLowestOffset)17 TEST(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 
28   TypeMemberInfo TM1{&VT1, 0};
29   TypeMemberInfo TM2{&VT2, 0};
30   VirtualCallTarget Targets[] = {
31     {&TM1, /*IsBigEndian=*/false},
32     {&TM2, /*IsBigEndian=*/false},
33   };
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 
41   TM1.Offset = 4;
42   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 
48   TM1.Offset = 8;
49   TM2.Offset = 8;
50   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 
TEST(WholeProgramDevirt,setReturnValues)62 TEST(WholeProgramDevirt, setReturnValues) {
63   VTableBits VT1;
64   VT1.ObjectSize = 8;
65 
66   VTableBits VT2;
67   VT2.ObjectSize = 8;
68 
69   TypeMemberInfo TM1{&VT1, 0};
70   TypeMemberInfo TM2{&VT2, 0};
71   VirtualCallTarget Targets[] = {
72     {&TM1, /*IsBigEndian=*/false},
73     {&TM2, /*IsBigEndian=*/false},
74   };
75 
76   TM1.Offset = 4;
77   TM2.Offset = 4;
78 
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 }
166