Home | History | Annotate | Download | only in IPO
      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 
     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 
     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