Skip to content

Commit 4d91b45

Browse files
authored
[RemoteMirror] Get spare bit info from reflection records (#40906)
This adds a new reflection record type carrying spare bit information for multi-payload enums. The compiler includes this for any type that might need it in order to accurately reflect the contents of the enum. The RemoteMirror library will use this if present to determine how to project the contents of the enum. If not present (for example, in older binaries), the RemoteMirror library falls back on an internal calculation of the spare bitmask. A few notes: * The internal calculation is not perfect. In particular, it does not support MPEs that contain other enums (e.g., optionals). It should accurately refuse to project any MPE that it does not correctly support. * The new reflection field is designed to be expandable; this might someday avoid the need for a new section. Resolves rdar://61158214
1 parent 45bacc2 commit 4d91b45

22 files changed

+1596
-78
lines changed

include/swift/Reflection/Records.h

Lines changed: 105 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -374,6 +374,111 @@ class BuiltinTypeDescriptor {
374374
}
375375
};
376376

377+
class MultiPayloadEnumDescriptor {
378+
public:
379+
const RelativeDirectPointer<const char> TypeName;
380+
381+
private:
382+
// This descriptor contains a series of 32-bit words
383+
uint32_t contents[];
384+
385+
// Properties are stored in `contents` at particular indexes:
386+
387+
// uint32_t SizeFlags;
388+
// Upper 16 bits are the size of the contents (in 32-bit words):
389+
// (This allows us to expand this structure in the future;
390+
// new fields should have accessors that test whether the
391+
// size is large enough and return "non-existent" if the
392+
// descriptor isn't large enough to have that field.)
393+
// Lower 16 bits are flag bits
394+
395+
int getSizeFlagsIndex() const { return 0; }
396+
397+
// uint32_t PayloadSpareBitMaskByteOffsetCount;
398+
// Number of bytes in "payload spare bits", and
399+
// offset of them within the payload area
400+
// Only present if `usePayloadSpareBits()`
401+
402+
int getPayloadSpareBitMaskByteCountIndex() const {
403+
return getSizeFlagsIndex() + 1;
404+
}
405+
406+
// uint8_t *PayloadSpareBits;
407+
// Variably-sized bitmask field (padded to a multiple of 4 bytes)
408+
// Only present if `usePayloadSpareBits()`
409+
410+
int getPayloadSpareBitsIndex() const {
411+
int PayloadSpareBitMaskByteCountFieldSize = usesPayloadSpareBits() ? 1 : 0;
412+
return getPayloadSpareBitMaskByteCountIndex() + PayloadSpareBitMaskByteCountFieldSize;
413+
}
414+
415+
// uint32_t foo;
416+
// TODO: Some future field
417+
// int getFooIndex() const {
418+
// int PayloadSpareBitMaskFieldSize = (getPayloadSpareBitMaskByteCount() + 3) / 4;
419+
// return getPayloadSpareBitsIndex() + PayloadSpareBitMaskFieldSize;
420+
// }
421+
422+
// uint32_t getFoo() const {
423+
// if (getFooIndex() < getContentsSizeInWords()) {
424+
// return contents[getFooIndex()];
425+
// } else {
426+
// return 0; // Field isn't present
427+
// }
428+
// }
429+
430+
public:
431+
//
432+
// Data derived from the above...
433+
//
434+
435+
uint32_t getContentsSizeInWords() const {
436+
return contents[getSizeFlagsIndex()] >> 16;
437+
}
438+
439+
size_t getSizeInBytes() const {
440+
// assert(getContentsSizeInWords() > 0 && "Malformed MPEnum reflection record");
441+
size_t sizeInBytes = sizeof(TypeName) + getContentsSizeInWords() * 4;
442+
return sizeInBytes;
443+
}
444+
445+
uint32_t getFlags() const {
446+
assert(getContentsSizeInWords() > 0 && "Malformed MPEnum reflection record");
447+
return contents[getSizeFlagsIndex()] & 0xffff;
448+
}
449+
450+
bool usesPayloadSpareBits() const {
451+
return getFlags() & 1;
452+
}
453+
454+
uint32_t getPayloadSpareBitMaskByteOffset() const {
455+
if (usesPayloadSpareBits()) {
456+
return contents[getPayloadSpareBitMaskByteCountIndex()] >> 16;
457+
} else {
458+
return 0;
459+
}
460+
}
461+
462+
uint32_t getPayloadSpareBitMaskByteCount() const {
463+
if (usesPayloadSpareBits()) {
464+
auto byteCount = contents[getPayloadSpareBitMaskByteCountIndex()] & 0xffff;
465+
assert(getContentsSizeInWords() >= 2 + (byteCount + 3) / 4
466+
&& "Malformed MPEnum reflection record: mask bigger than record");
467+
return byteCount;
468+
} else {
469+
return 0;
470+
}
471+
}
472+
473+
const uint8_t *getPayloadSpareBits() const {
474+
if (usesPayloadSpareBits()) {
475+
return reinterpret_cast<const uint8_t *>(&contents[getPayloadSpareBitsIndex()]);
476+
} else {
477+
return nullptr;
478+
}
479+
}
480+
};
481+
377482
class CaptureTypeRecord {
378483
public:
379484
const RelativeDirectPointer<const char> MangledTypeName;

include/swift/Reflection/ReflectionContext.h

Lines changed: 20 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -272,14 +272,17 @@ class ReflectionContext
272272
ObjectFileFormat.getSectionName(ReflectionSectionKind::reflstr));
273273
auto ConformMdSec = findMachOSectionByName(
274274
ObjectFileFormat.getSectionName(ReflectionSectionKind::conform));
275+
auto MPEnumMdSec = findMachOSectionByName(
276+
ObjectFileFormat.getSectionName(ReflectionSectionKind::mpenum));
275277

276278
if (FieldMdSec.first == nullptr &&
277279
AssocTySec.first == nullptr &&
278280
BuiltinTySec.first == nullptr &&
279281
CaptureSec.first == nullptr &&
280282
TypeRefMdSec.first == nullptr &&
281283
ReflStrMdSec.first == nullptr &&
282-
ConformMdSec.first == nullptr)
284+
ConformMdSec.first == nullptr &&
285+
MPEnumMdSec.first == nullptr)
283286
return false;
284287

285288
ReflectionInfo info = {
@@ -289,7 +292,8 @@ class ReflectionContext
289292
{CaptureSec.first, CaptureSec.second},
290293
{TypeRefMdSec.first, TypeRefMdSec.second},
291294
{ReflStrMdSec.first, ReflStrMdSec.second},
292-
{ConformMdSec.first, ConformMdSec.second}};
295+
{ConformMdSec.first, ConformMdSec.second},
296+
{MPEnumMdSec.first, MPEnumMdSec.second}};
293297

294298
this->addReflectionInfo(info);
295299

@@ -394,14 +398,17 @@ class ReflectionContext
394398
ObjectFileFormat.getSectionName(ReflectionSectionKind::reflstr));
395399
auto ConformMdSec = findCOFFSectionByName(
396400
ObjectFileFormat.getSectionName(ReflectionSectionKind::conform));
401+
auto MPEnumMdSec = findCOFFSectionByName(
402+
ObjectFileFormat.getSectionName(ReflectionSectionKind::mpenum));
397403

398404
if (FieldMdSec.first == nullptr &&
399405
AssocTySec.first == nullptr &&
400406
BuiltinTySec.first == nullptr &&
401407
CaptureSec.first == nullptr &&
402408
TypeRefMdSec.first == nullptr &&
403409
ReflStrMdSec.first == nullptr &&
404-
ConformMdSec.first == nullptr)
410+
ConformMdSec.first == nullptr &&
411+
MPEnumMdSec.first == nullptr)
405412
return false;
406413

407414
ReflectionInfo Info = {
@@ -411,7 +418,8 @@ class ReflectionContext
411418
{CaptureSec.first, CaptureSec.second},
412419
{TypeRefMdSec.first, TypeRefMdSec.second},
413420
{ReflStrMdSec.first, ReflStrMdSec.second},
414-
{ConformMdSec.first, ConformMdSec.second}};
421+
{ConformMdSec.first, ConformMdSec.second},
422+
{MPEnumMdSec.first, MPEnumMdSec.second}};
415423
this->addReflectionInfo(Info);
416424
return true;
417425
}
@@ -577,6 +585,8 @@ class ReflectionContext
577585
ObjectFileFormat.getSectionName(ReflectionSectionKind::reflstr));
578586
auto ConformMdSec = findELFSectionByName(
579587
ObjectFileFormat.getSectionName(ReflectionSectionKind::conform));
588+
auto MPEnumMdSec = findELFSectionByName(
589+
ObjectFileFormat.getSectionName(ReflectionSectionKind::mpenum));
580590

581591
if (Error)
582592
return false;
@@ -589,7 +599,8 @@ class ReflectionContext
589599
CaptureSec.first == nullptr &&
590600
TypeRefMdSec.first == nullptr &&
591601
ReflStrMdSec.first == nullptr &&
592-
ConformMdSec.first == nullptr)
602+
ConformMdSec.first == nullptr &&
603+
MPEnumMdSec.first == nullptr)
593604
return false;
594605

595606
ReflectionInfo info = {
@@ -599,7 +610,8 @@ class ReflectionContext
599610
{CaptureSec.first, CaptureSec.second},
600611
{TypeRefMdSec.first, TypeRefMdSec.second},
601612
{ReflStrMdSec.first, ReflStrMdSec.second},
602-
{ConformMdSec.first, ConformMdSec.second}};
613+
{ConformMdSec.first, ConformMdSec.second},
614+
{MPEnumMdSec.first, MPEnumMdSec.second}};
603615

604616
this->addReflectionInfo(info);
605617
return true;
@@ -701,8 +713,7 @@ class ReflectionContext
701713
ReflectionSectionKind::fieldmd, ReflectionSectionKind::assocty,
702714
ReflectionSectionKind::builtin, ReflectionSectionKind::capture,
703715
ReflectionSectionKind::typeref, ReflectionSectionKind::reflstr,
704-
ReflectionSectionKind::conform
705-
};
716+
ReflectionSectionKind::conform, ReflectionSectionKind::mpenum};
706717

707718
llvm::SmallVector<std::pair<RemoteRef<void>, uint64_t>, 6> Pairs;
708719
for (auto Section : Sections) {
@@ -725,7 +736,7 @@ class ReflectionContext
725736
{Pairs[0].first, Pairs[0].second}, {Pairs[1].first, Pairs[1].second},
726737
{Pairs[2].first, Pairs[2].second}, {Pairs[3].first, Pairs[3].second},
727738
{Pairs[4].first, Pairs[4].second}, {Pairs[5].first, Pairs[5].second},
728-
{Pairs[6].first, Pairs[6].second}};
739+
{Pairs[6].first, Pairs[6].second}, {Pairs[7].first, Pairs[7].second}};
729740
this->addReflectionInfo(Info);
730741
return true;
731742
}

include/swift/Reflection/TypeLowering.h

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -360,6 +360,11 @@ class TypeConverter {
360360
getClassInstanceTypeInfo(const TypeRef *TR, unsigned start,
361361
remote::TypeInfoProvider *ExternalTypeInfo);
362362

363+
unsigned targetPointerSize() {
364+
auto *rawPointerTI = getTypeInfo(getRawPointerTypeRef(), nullptr);
365+
return rawPointerTI->getSize();
366+
}
367+
363368
private:
364369
friend class swift::reflection::LowerType;
365370
friend class swift::reflection::EnumTypeInfoBuilder;

0 commit comments

Comments
 (0)