/// Build a bit set for BitSet using the object layouts in /// GlobalLayout. BitSetInfo LowerBitSets::buildBitSet( Metadata *BitSet, const DenseMap<GlobalObject *, uint64_t> &GlobalLayout) { BitSetBuilder BSB; // Compute the byte offset of each element of this bitset. if (BitSetNM) { for (MDNode *Op : BitSetNM->operands()) { if (Op->getOperand(0) != BitSet || !Op->getOperand(1)) continue; Constant *OpConst = cast<ConstantAsMetadata>(Op->getOperand(1))->getValue(); if (auto GA = dyn_cast<GlobalAlias>(OpConst)) OpConst = GA->getAliasee(); auto OpGlobal = dyn_cast<GlobalObject>(OpConst); if (!OpGlobal) continue; uint64_t Offset = cast<ConstantInt>(cast<ConstantAsMetadata>(Op->getOperand(2)) ->getValue())->getZExtValue(); Offset += GlobalLayout.find(OpGlobal)->second; BSB.addOffset(Offset); } } return BSB.build(); }
/// Build a bit set for TypeId using the object layouts in /// GlobalLayout. BitSetInfo LowerTypeTestsModule::buildBitSet( Metadata *TypeId, const DenseMap<GlobalObject *, uint64_t> &GlobalLayout) { BitSetBuilder BSB; // Compute the byte offset of each address associated with this type // identifier. SmallVector<MDNode *, 2> Types; for (auto &GlobalAndOffset : GlobalLayout) { Types.clear(); GlobalAndOffset.first->getMetadata(LLVMContext::MD_type, Types); for (MDNode *Type : Types) { if (Type->getOperand(1) != TypeId) continue; uint64_t Offset = cast<ConstantInt>( cast<ConstantAsMetadata>(Type->getOperand(0))->getValue()) ->getZExtValue(); BSB.addOffset(GlobalAndOffset.second + Offset); } } return BSB.build(); }
TEST(LowerTypeTests, BitSetBuilder) { struct { std::vector<uint64_t> Offsets; std::set<uint64_t> Bits; uint64_t ByteOffset; uint64_t BitSize; unsigned AlignLog2; bool IsSingleOffset; bool IsAllOnes; } BSBTests[] = { {{}, std::set<uint64_t>{}, 0, 1, 0, false, false}, {{0}, {0}, 0, 1, 0, true, true}, {{4}, {0}, 4, 1, 0, true, true}, {{37}, {0}, 37, 1, 0, true, true}, {{0, 1}, {0, 1}, 0, 2, 0, false, true}, {{0, 4}, {0, 1}, 0, 2, 2, false, true}, {{0, uint64_t(1) << 33}, {0, 1}, 0, 2, 33, false, true}, {{3, 7}, {0, 1}, 3, 2, 2, false, true}, {{0, 1, 7}, {0, 1, 7}, 0, 8, 0, false, false}, {{0, 2, 14}, {0, 1, 7}, 0, 8, 1, false, false}, {{0, 1, 8}, {0, 1, 8}, 0, 9, 0, false, false}, {{0, 2, 16}, {0, 1, 8}, 0, 9, 1, false, false}, { {0, 1, 2, 3, 4, 5, 6, 7}, {0, 1, 2, 3, 4, 5, 6, 7}, 0, 8, 0, false, true }, { {0, 1, 2, 3, 4, 5, 6, 7, 8}, {0, 1, 2, 3, 4, 5, 6, 7, 8}, 0, 9, 0, false, true }, }; for (auto &&T : BSBTests) { BitSetBuilder BSB; for (auto Offset : T.Offsets) BSB.addOffset(Offset); BitSetInfo BSI = BSB.build(); EXPECT_EQ(T.Bits, BSI.Bits); EXPECT_EQ(T.ByteOffset, BSI.ByteOffset); EXPECT_EQ(T.BitSize, BSI.BitSize); EXPECT_EQ(T.AlignLog2, BSI.AlignLog2); EXPECT_EQ(T.IsSingleOffset, BSI.isSingleOffset()); EXPECT_EQ(T.IsAllOnes, BSI.isAllOnes()); for (auto Offset : T.Offsets) EXPECT_TRUE(BSI.containsGlobalOffset(Offset)); auto I = T.Offsets.begin(); for (uint64_t NonOffset = 0; NonOffset != 256; ++NonOffset) { if (I != T.Offsets.end() && *I == NonOffset) { ++I; continue; } EXPECT_FALSE(BSI.containsGlobalOffset(NonOffset)); } } }