Go to the documentation of this file.
54 uint32_t calculateSerializedLength()
const;
57 void finalizePublicBuckets();
58 void finalizeGlobalBuckets(
uint32_t RecordZeroOffset);
63 void finalizeBuckets(
uint32_t RecordZeroOffset,
82 return LHS.RecordData ==
RHS.RecordData;
88 struct PublicSym32Layout {
101 return alignTo(
sizeof(PublicSym32Layout) + NameLen + 1, 4);
108 size_t Size =
alignTo(
sizeof(PublicSym32Layout) + NameLen + 1, 4);
110 auto *FixedMem =
reinterpret_cast<PublicSym32Layout *
>(Mem);
111 FixedMem->Prefix.RecordKind =
static_cast<uint16_t>(codeview::S_PUB32);
112 FixedMem->Prefix.RecordLen =
static_cast<uint16_t>(Size - 2);
113 FixedMem->Pub.Flags =
Pub.Flags;
114 FixedMem->Pub.Offset =
Pub.Offset;
115 FixedMem->Pub.Segment =
Pub.Segment;
116 char *NameMem =
reinterpret_cast<char *
>(FixedMem + 1);
119 memset(&NameMem[NameLen], 0, Size -
sizeof(PublicSym32Layout) - NameLen);
123 uint32_t GSIHashStreamBuilder::calculateSerializedLength()
const {
126 Size += HashBitmap.size() *
sizeof(
uint32_t);
127 Size += HashBuckets.size() *
sizeof(
uint32_t);
134 Header.
VerHdr = GSIHashHeader::HdrVersion;
136 Header.
NumBuckets = HashBitmap.size() * 4 + HashBuckets.size() * 4;
157 size_t RS = S2.
size();
160 return (
LS > RS) - (
LS < RS);
170 void GSIStreamBuilder::finalizePublicBuckets() {
171 PSH->finalizeBuckets(0, Publics);
174 void GSIStreamBuilder::finalizeGlobalBuckets(
uint32_t RecordZeroOffset) {
183 std::vector<BulkPublic> Records;
184 Records.resize(Globals.size());
185 uint32_t SymOffset = RecordZeroOffset;
186 for (
size_t I = 0,
E = Globals.size();
I <
E; ++
I) {
188 Records[
I].Name =
Name.data();
189 Records[
I].NameLen =
Name.size();
190 Records[
I].SymOffset = SymOffset;
191 SymOffset += Globals[
I].length();
194 GSH->finalizeBuckets(RecordZeroOffset, Records);
197 void GSIHashStreamBuilder::finalizeBuckets(
201 Records[I].setBucketIdx(hashStringV1(Records[I].Name) % IPHR_HASH);
209 ++BucketStarts[
P.BucketIdx];
220 HashRecords.resize(Records.size());
222 memcpy(BucketCursors, BucketStarts,
sizeof(BucketCursors));
223 for (
int I = 0,
E = Records.size();
I <
E; ++
I) {
224 uint32_t HashIdx = BucketCursors[Records[
I].BucketIdx]++;
225 HashRecords[HashIdx].Off =
I;
226 HashRecords[HashIdx].CRef = 1;
236 auto B = HashRecords.begin() + BucketStarts[
I];
237 auto E = HashRecords.begin() + BucketCursors[
I];
259 HRec.Off = Records[
uint32_t(HRec.Off)].SymOffset + 1;
270 BucketStarts[BucketIdx] == BucketCursors[BucketIdx])
277 const int SizeOfHROffsetCalc = 12;
279 ulittle32_t(BucketStarts[BucketIdx] * SizeOfHROffsetCalc);
280 HashBuckets.push_back(ChainStartOff);
282 HashBitmap[
I] =
Word;
292 uint32_t GSIStreamBuilder::calculatePublicsHashStreamSize()
const {
295 Size += PSH->calculateSerializedLength();
296 Size += Publics.size() *
sizeof(
uint32_t);
302 uint32_t GSIStreamBuilder::calculateGlobalsHashStreamSize()
const {
303 return GSH->calculateSerializedLength();
308 finalizePublicBuckets();
309 finalizeGlobalBuckets(PSH->RecordByteSize);
314 GlobalsStreamIndex = *Idx;
316 Idx = Msf.
addStream(calculatePublicsHashStreamSize());
319 PublicsStreamIndex = *Idx;
321 uint32_t RecordBytes = PSH->RecordByteSize + GSH->RecordByteSize;
326 RecordStreamIndex = *Idx;
331 assert(Publics.empty() && PSH->RecordByteSize == 0 &&
332 "publics can only be added once");
337 return L.
getName() < R.getName();
343 Pub.SymOffset = SymOffset;
348 PSH->RecordByteSize = SymOffset;
352 serializeAndAddGlobal(Sym);
356 serializeAndAddGlobal(Sym);
360 serializeAndAddGlobal(Sym);
363 template <
typename T>
364 void GSIStreamBuilder::serializeAndAddGlobal(
const T &
Symbol) {
367 CodeViewContainer::Pdb));
372 if (
Symbol.kind() == S_UDT ||
Symbol.kind() == S_CONSTANT) {
373 auto Iter = GlobalsSeen.insert(
Symbol);
377 GSH->RecordByteSize +=
Symbol.length();
378 Globals.push_back(
Symbol);
384 std::vector<uint8_t> Storage;
402 Error GSIStreamBuilder::commitSymbolRecordStream(
417 static std::vector<support::ulittle32_t>
421 std::vector<ulittle32_t> PubAddrMap;
422 PubAddrMap.reserve(Publics.
size());
423 for (
int I = 0,
E = Publics.
size();
I <
E; ++
I)
432 return L.
Offset < R.Offset;
435 return L.
getName() < R.getName();
441 Entry = Publics[Entry].SymOffset;
445 Error GSIStreamBuilder::commitPublicsHashStream(
451 Header.
SymHash = PSH->calculateSerializedLength();
452 Header.
AddrMap = Publics.size() * 4;
459 if (
auto EC = Writer.writeObject(Header))
462 if (
auto EC = PSH->commit(Writer))
465 std::vector<support::ulittle32_t> PubAddrMap =
computeAddrMap(Publics);
466 assert(PubAddrMap.size() == Publics.size());
467 if (
auto EC = Writer.writeArray(
makeArrayRef(PubAddrMap)))
473 Error GSIStreamBuilder::commitGlobalsHashStream(
476 return GSH->commit(Writer);
481 auto GS = WritableMappedBlockStream::createIndexedStream(
483 auto PS = WritableMappedBlockStream::createIndexedStream(
485 auto PRS = WritableMappedBlockStream::createIndexedStream(
488 if (
auto EC = commitSymbolRecordStream(*PRS))
490 if (
auto EC = commitGlobalsHashStream(*
GS))
492 if (
auto EC = commitPublicsHashStream(*PS))
uint64_t alignTo(uint64_t Size, Align A)
Returns a multiple of A needed to store Size bytes.
static CVSymbol getEmptyKey()
This is an optimization pass for GlobalISel generic memory operations.
iterator_range< T > make_range(T x, T y)
Convenience function for iterating over sub-ranges.
#define LLVM_PACKED_START
std::vector< PSHashRecord > HashRecords
uint32_t getGlobalsStreamIndex() const
This currently compiles esp xmm0 movsd esp eax eax esp ret We should use not the dag combiner This is because dagcombine2 needs to be able to see through the X86ISD::Wrapper which DAGCombine can t really do The code for turning x load into a single vector load is target independent and should be moved to the dag combiner The code for turning x load into a vector load can only handle a direct load from a global or a direct load from the stack It should be generalized to handle any load from P
uint32_t getPublicsStreamIndex() const
Provides write only access to a subclass of WritableBinaryStream.
static ErrorSuccess success()
Create a success value.
Error writeStreamRef(BinaryStreamRef Ref)
Efficiently reads all data from Ref, and writes it to this stream.
Merge contiguous icmps into a memcmp
static Error writeRecords(BinaryStreamWriter &Writer, ArrayRef< CVSymbol > Records)
Expected< uint32_t > addStream(uint32_t Size, ArrayRef< uint32_t > Blocks)
Add a stream to the MSF file with the given size, occupying the given list of blocks.
Error writeArray(ArrayRef< T > Array)
Writes an array of objects of type T to the underlying stream, as if by using memcpy.
Tagged union holding either a T or a Error.
ArrayRef< uint8_t > RecordData
StringRef getName() const
An information struct used to provide DenseMap with the various necessary components for a given valu...
@ Pub
.debug_pubnames, .debug_pubtypes
bool all_of(R &&range, UnaryPredicate P)
Provide wrappers to std::all_of which take ranges instead of having to pass begin/end explicitly.
uint32_t getRecordStreamIndex() const
MutableArrayRef - Represent a mutable reference to an array (0 or more elements consecutively in memo...
static Error writePublics(BinaryStreamWriter &Writer, ArrayRef< BulkPublic > Publics)
static GCRegistry::Add< CoreCLRGC > E("coreclr", "CoreCLR-compatible GC")
(vector float) vec_cmpeq(*A, *B) C
static CVSymbol serializePublic(uint8_t *Mem, const BulkPublic &Pub)
CVRecord< SymbolKind > CVSymbol
static GCRegistry::Add< OcamlGC > B("ocaml", "ocaml 3.10-compatible GC")
void addGlobalSymbol(const codeview::ProcRefSym &Sym)
std::vector< support::ulittle32_t > HashBuckets
static bool isEqual(const CVSymbol &LHS, const CVSymbol &RHS)
detail::packed_endian_specific_integral< uint32_t, little, unaligned > ulittle32_t
This struct is equivalent to codeview::PublicSym32, but it has been optimized for size to speed up bu...
compiles ldr LCPI1_0 ldr ldr mov lsr tst moveq r1 ldr LCPI1_1 and r0 bx lr It would be better to do something like to fold the shift into the conditional move
Error finalizeMsfLayout()
assert(ImpDefSCC.getReg()==AMDGPU::SCC &&ImpDefSCC.isDef())
<%struct.s * > cast struct s *S to sbyte *< sbyte * > sbyte uint cast struct s *agg result to sbyte *< sbyte * > sbyte uint cast struct s *memtmp to sbyte *< sbyte * > sbyte uint ret void llc ends up issuing two memcpy or custom lower memcpy(of small size) to be ldmia/stmia. I think option 2 is better but the current register allocator cannot allocate a chunk of registers at a time. A feasible temporary solution is to use specific physical registers at the lowering time for small(<
Error commit(const msf::MSFLayout &Layout, WritableBinaryStreamRef Buffer)
void setItems(ArrayRef< T > ItemArray)
void addPublicSymbols(std::vector< BulkPublic > &&PublicsIn)
support::ulittle32_t Word
Error writeObject(const T &Obj)
Writes the object Obj to the underlying stream, as if by using memcpy.
Expected< ExpressionValue > min(const ExpressionValue &Lhs, const ExpressionValue &Rhs)
static std::vector< support::ulittle32_t > computeAddrMap(ArrayRef< BulkPublic > Publics)
Error writeBytes(ArrayRef< uint8_t > Buffer)
Write the bytes specified in Buffer to the underlying stream.
StringRef - Represent a constant reference to a string, i.e.
CVRecord is a fat pointer (base + size pair) to a symbol or type record.
void parallelSort(RandomAccessIterator Start, RandomAccessIterator End, const Comparator &Comp=Comparator())
add sub stmia L5 ldr r0 bl L_printf $stub Instead of a and a wouldn t it be better to do three moves *Return an aggregate type is even return S
static uint32_t sizeOfPublic(const BulkPublic &Pub)
static unsigned getHashValue(const CVSymbol &Val)
BumpPtrAllocator & getAllocator()
constexpr LLVM_NODISCARD size_t size() const
size - Get the string size.
void parallelFor(size_t Begin, size_t End, function_ref< void(size_t)> Fn)
Lightweight error class with error context and mandatory checking.
void sort(IteratorTy Start, IteratorTy End)
static CVSymbol getTombstoneKey()
BinaryItemStream represents a sequence of objects stored in some kind of external container but for w...
ArrayRef< T > makeArrayRef(const T &OneElt)
Construct an ArrayRef from a single element.
Error takeError()
Take ownership of the stored error.
LLVM_NODISCARD int compare_insensitive(StringRef RHS) const
Compare two strings, ignoring case.
size_t size() const
size - Get the array size.
const LLVM_NODISCARD char * data() const
data - Get a pointer to the start of the string (which may not be null terminated).
static bool isAsciiString(StringRef S)
#define LLVM_UNLIKELY(EXPR)
static StringRef getSymbolName(SymbolKind SymKind)
static int gsiRecordCmp(StringRef S1, StringRef S2)
uint64_t xxHash64(llvm::StringRef Data)
BinaryStreamRef is to BinaryStream what ArrayRef is to an Array.