165 lines · cpp
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-exception6//7//===----------------------------------------------------------------------===//8 9#include "llvm/Transforms/IPO/WholeProgramDevirt.h"10#include "llvm/ADT/ArrayRef.h"11#include "gtest/gtest.h"12 13using namespace llvm;14using namespace wholeprogramdevirt;15 16TEST(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(64ull, findLowestOffset(Targets, /*IsAfter=*/true, 32));59}60 61TEST(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