void CodeGenVTables::createVTableInitializer(ConstantStructBuilder &builder, const VTableLayout &layout, llvm::Constant *rtti) { unsigned nextVTableThunkIndex = 0; for (unsigned i = 0, e = layout.getNumVTables(); i != e; ++i) { auto vtableElem = builder.beginArray(CGM.Int8PtrTy); size_t thisIndex = layout.getVTableOffset(i); size_t nextIndex = thisIndex + layout.getVTableSize(i); for (unsigned i = thisIndex; i != nextIndex; ++i) { addVTableComponent(vtableElem, layout, i, rtti, nextVTableThunkIndex); } vtableElem.finishAndAddTo(builder); } }
void CodeGenModule::EmitVTableTypeMetadata(llvm::GlobalVariable *VTable, const VTableLayout &VTLayout) { if (!getCodeGenOpts().LTOUnit) return; CharUnits PointerWidth = Context.toCharUnitsFromBits(Context.getTargetInfo().getPointerWidth(0)); typedef std::pair<const CXXRecordDecl *, unsigned> BSEntry; std::vector<BSEntry> BitsetEntries; // Create a bit set entry for each address point. for (auto &&AP : VTLayout.getAddressPoints()) BitsetEntries.push_back( std::make_pair(AP.first.getBase(), VTLayout.getVTableOffset(AP.second.VTableIndex) + AP.second.AddressPointIndex)); // Sort the bit set entries for determinism. std::sort(BitsetEntries.begin(), BitsetEntries.end(), [this](const BSEntry &E1, const BSEntry &E2) { if (&E1 == &E2) return false; std::string S1; llvm::raw_string_ostream O1(S1); getCXXABI().getMangleContext().mangleTypeName( QualType(E1.first->getTypeForDecl(), 0), O1); O1.flush(); std::string S2; llvm::raw_string_ostream O2(S2); getCXXABI().getMangleContext().mangleTypeName( QualType(E2.first->getTypeForDecl(), 0), O2); O2.flush(); if (S1 < S2) return true; if (S1 != S2) return false; return E1.second < E2.second; }); for (auto BitsetEntry : BitsetEntries) AddVTableTypeMetadata(VTable, PointerWidth * BitsetEntry.second, BitsetEntry.first); }
void CodeGenModule::EmitVTableTypeMetadata(llvm::GlobalVariable *VTable, const VTableLayout &VTLayout) { if (!getCodeGenOpts().LTOUnit) return; CharUnits PointerWidth = Context.toCharUnitsFromBits(Context.getTargetInfo().getPointerWidth(0)); typedef std::pair<const CXXRecordDecl *, unsigned> AddressPoint; std::vector<AddressPoint> AddressPoints; for (auto &&AP : VTLayout.getAddressPoints()) AddressPoints.push_back(std::make_pair( AP.first.getBase(), VTLayout.getVTableOffset(AP.second.VTableIndex) + AP.second.AddressPointIndex)); // Sort the address points for determinism. llvm::sort(AddressPoints, [this](const AddressPoint &AP1, const AddressPoint &AP2) { if (&AP1 == &AP2) return false; std::string S1; llvm::raw_string_ostream O1(S1); getCXXABI().getMangleContext().mangleTypeName( QualType(AP1.first->getTypeForDecl(), 0), O1); O1.flush(); std::string S2; llvm::raw_string_ostream O2(S2); getCXXABI().getMangleContext().mangleTypeName( QualType(AP2.first->getTypeForDecl(), 0), O2); O2.flush(); if (S1 < S2) return true; if (S1 != S2) return false; return AP1.second < AP2.second; }); ArrayRef<VTableComponent> Comps = VTLayout.vtable_components(); for (auto AP : AddressPoints) { // Create type metadata for the address point. AddVTableTypeMetadata(VTable, PointerWidth * AP.second, AP.first); // The class associated with each address point could also potentially be // used for indirect calls via a member function pointer, so we need to // annotate the address of each function pointer with the appropriate member // function pointer type. for (unsigned I = 0; I != Comps.size(); ++I) { if (Comps[I].getKind() != VTableComponent::CK_FunctionPointer) continue; llvm::Metadata *MD = CreateMetadataIdentifierForVirtualMemPtrType( Context.getMemberPointerType( Comps[I].getFunctionDecl()->getType(), Context.getRecordType(AP.first).getTypePtr())); VTable->addTypeMetadata((PointerWidth * I).getQuantity(), MD); } } }