Files
swift-mirror/lib/IRGen/EnumMetadataLayout.h
Joe Groff 0b339b9a46 IRGen: Populate nominal type descriptor metadata for enums.
Store the number of payload and no-payload cases, the case names, and a lazy case type accessor function for enums, like we do for stored properties of structs and classes. This will be useful for multi-payload runtime support, and should also be enough info to hack together a reflection implementation for enums.

For dynamic multi-payload enums to not be ridiculously inefficient, we'll need to track the size of the payload area in the enum, like we do the field offsets of generic structs and classes, so hack off a byte in the payload case count to track the offset of that field in metadata records. 16 million payloads ought to be enough for anyone, right? (and 256 words between the enum metadata's address point and the payload size offset)

Swift SVN r27789
2015-04-27 00:35:04 +00:00

102 lines
3.0 KiB
C++

//===--- EnumMetadataLayout.h - CRTP for enum metadata ------*- C++ -*-===//
//
// This source file is part of the Swift.org open source project
//
// Copyright (c) 2014 - 2015 Apple Inc. and the Swift project authors
// Licensed under Apache License v2.0 with Runtime Library Exception
//
// See http://swift.org/LICENSE.txt for license information
// See http://swift.org/CONTRIBUTORS.txt for the list of Swift project authors
//
//===----------------------------------------------------------------------===//
//
// A CRTP class useful for laying out enum metadata.
//
//===----------------------------------------------------------------------===//
#ifndef SWIFT_IRGEN_ENUMMETADATALAYOUT_H
#define SWIFT_IRGEN_ENUMMETADATALAYOUT_H
#include "MetadataLayout.h"
namespace swift {
namespace irgen {
/// A CRTP class for laying out enum metadata.
///
/// This produces an object corresponding to the EnumMetadata type.
/// It does not itself doing anything special for metadata templates.
template <class Impl> class EnumMetadataLayout : public MetadataLayout<Impl> {
typedef MetadataLayout<Impl> super;
protected:
using super::IGM;
using super::asImpl;
/// The Enum.
EnumDecl *const Target;
EnumMetadataLayout(IRGenModule &IGM, EnumDecl *target)
: super(IGM), Target(target) {}
public:
void layout() {
// Metadata header.
super::layout();
// EnumMetadata header.
asImpl().addNominalTypeDescriptor();
asImpl().addParentMetadataRef();
// If changing this layout, you must update the magic number in
// emitParentMetadataRef.
// Instantiation-specific.
// Reserve a word to cache the payload size if the type has dynamic layout.
auto &strategy = getEnumImplStrategy(IGM,
Target->DeclContext::getDeclaredTypeInContext()->getCanonicalType());
if (strategy.needsPayloadSizeInMetadata())
asImpl().addPayloadSize();
// Add fields for generic cases.
if (auto generics = Target->getGenericParamsOfContext())
asImpl().addGenericFields(*generics);
}
};
/// An "implementation" of EnumMetadataLayout that just scans through
/// the metadata layout, maintaining the next index: the offset (in
/// pointer-sized chunks) into the metadata for the next field.
template <class Impl>
class EnumMetadataScanner : public EnumMetadataLayout<Impl> {
typedef EnumMetadataLayout<Impl> super;
protected:
Size NextOffset = Size(0);
EnumMetadataScanner(IRGenModule &IGM, EnumDecl *target)
: super(IGM, target) {}
public:
void addMetadataFlags() { addPointer(); }
void addValueWitnessTable() { addPointer(); }
void addNominalTypeDescriptor() { addPointer(); }
void addParentMetadataRef() { addPointer(); }
void addGenericArgument(ArchetypeType *argument) { addPointer(); }
void addGenericWitnessTable(ArchetypeType *argument,
ProtocolDecl *protocol) {
addPointer();
}
void addPayloadSize() { addPointer(); }
private:
void addPointer() {
NextOffset += super::IGM.getPointerSize();
}
};
} // end namespace irgen
} // end namespace swift
#endif