TEST(LowerTypeTests, ByteArrayBuilder) { struct BABAlloc { std::set<uint64_t> Bits; uint64_t BitSize; uint64_t WantByteOffset; uint8_t WantMask; }; struct { std::vector<BABAlloc> Allocs; std::vector<uint8_t> WantBytes; } BABTests[] = { {{{{0}, 1, 0, 1}, {{0}, 1, 0, 2}}, {3}}, { { {{0}, 16, 0, 1}, {{1}, 15, 0, 2}, {{2}, 14, 0, 4}, {{3}, 13, 0, 8}, {{4}, 12, 0, 0x10}, {{5}, 11, 0, 0x20}, {{6}, 10, 0, 0x40}, {{7}, 9, 0, 0x80}, {{0}, 7, 9, 0x80}, {{0}, 6, 10, 0x40}, {{0}, 5, 11, 0x20}, {{0}, 4, 12, 0x10}, {{0}, 3, 13, 8}, {{0}, 2, 14, 4}, {{0}, 1, 15, 2} }, { 1, 2, 4, 8, 0x10, 0x20, 0x40, 0x80, 0, 0x80, 0x40, 0x20, 0x10, 8, 4, 2 } }, }; for (auto &&T : BABTests) { ByteArrayBuilder BABuilder; for (auto &&A : T.Allocs) { uint64_t GotByteOffset; uint8_t GotMask; BABuilder.allocate(A.Bits, A.BitSize, GotByteOffset, GotMask); EXPECT_EQ(A.WantByteOffset, GotByteOffset); EXPECT_EQ(A.WantMask, GotMask); } EXPECT_EQ(T.WantBytes, BABuilder.Bytes); } }
void LowerBitSets::allocateByteArrays() { std::stable_sort(ByteArrayInfos.begin(), ByteArrayInfos.end(), [](const ByteArrayInfo &BAI1, const ByteArrayInfo &BAI2) { return BAI1.BitSize > BAI2.BitSize; }); std::vector<uint64_t> ByteArrayOffsets(ByteArrayInfos.size()); ByteArrayBuilder BAB; for (unsigned I = 0; I != ByteArrayInfos.size(); ++I) { ByteArrayInfo *BAI = &ByteArrayInfos[I]; uint8_t Mask; BAB.allocate(BAI->Bits, BAI->BitSize, ByteArrayOffsets[I], Mask); BAI->Mask->replaceAllUsesWith(ConstantInt::get(Int8Ty, Mask)); cast<GlobalVariable>(BAI->Mask->getOperand(0))->eraseFromParent(); } Constant *ByteArrayConst = ConstantDataArray::get(M->getContext(), BAB.Bytes); auto ByteArray = new GlobalVariable(*M, ByteArrayConst->getType(), /*isConstant=*/true, GlobalValue::PrivateLinkage, ByteArrayConst); for (unsigned I = 0; I != ByteArrayInfos.size(); ++I) { ByteArrayInfo *BAI = &ByteArrayInfos[I]; Constant *Idxs[] = {ConstantInt::get(IntPtrTy, 0), ConstantInt::get(IntPtrTy, ByteArrayOffsets[I])}; Constant *GEP = ConstantExpr::getInBoundsGetElementPtr( ByteArrayConst->getType(), ByteArray, Idxs); // Create an alias instead of RAUW'ing the gep directly. On x86 this ensures // that the pc-relative displacement is folded into the lea instead of the // test instruction getting another displacement. if (LinkerSubsectionsViaSymbols) { BAI->ByteArray->replaceAllUsesWith(GEP); } else { GlobalAlias *Alias = GlobalAlias::create( Int8Ty, 0, GlobalValue::PrivateLinkage, "bits", GEP, M); BAI->ByteArray->replaceAllUsesWith(Alias); } BAI->ByteArray->eraseFromParent(); } ByteArraySizeBits = BAB.BitAllocs[0] + BAB.BitAllocs[1] + BAB.BitAllocs[2] + BAB.BitAllocs[3] + BAB.BitAllocs[4] + BAB.BitAllocs[5] + BAB.BitAllocs[6] + BAB.BitAllocs[7]; ByteArraySizeBytes = BAB.Bytes.size(); }
bool ServiceSnacHandler::sendServices(const QByteArray& data) { OscarSocket* socket = client()->oscarSocket(); Q_ASSERT(socket); ByteArrayBuilder builder; if(client()->isAim()) { builder.appendDword(0x00010003L); builder.appendDword(0x00130003L); builder.appendDword(0x00020001L); builder.appendDword(0x00030001L); builder.appendDword(0x00040001L); builder.appendDword(0x00060001L); builder.appendDword(0x00080001L); builder.appendDword(0x00090001L); builder.appendDword(0x000A0001L); builder.appendDword(0x000B0001L); } else { builder.appendDword(0x00010004L); builder.appendDword(0x00130004L); builder.appendDword(0x00020001L); builder.appendDword(0x00030001L); builder.appendDword(0x00150001L); builder.appendDword(0x00040001L); builder.appendDword(0x00060001L); builder.appendDword(0x00090001L); builder.appendDword(0x000A0001L); builder.appendDword(0x000B0001L); } socket->snac(ICQ_SNACxFOOD_SERVICE, SnacServiceCapabilities, 0, builder.getArray()); return true; }