blob: 7edc2d94a8313dc1e1a150006553a3c555f38eaa [file] [log] [blame]
//===--- ResilientTypeInfo.h - Resilient-layout types -----------*- C++ -*-===//
//
// This source file is part of the Swift.org open source project
//
// Copyright (c) 2014 - 2017 Apple Inc. and the Swift project authors
// Licensed under Apache License v2.0 with Runtime Library Exception
//
// See https://swift.org/LICENSE.txt for license information
// See https://swift.org/CONTRIBUTORS.txt for the list of Swift project authors
//
//===----------------------------------------------------------------------===//
//
// This file defines a class used for implementing non-class-bound
// archetypes, and resilient structs and enums. Values of these types are
// opaque and must be manipulated through value witness function calls.
//
//===----------------------------------------------------------------------===//
#ifndef SWIFT_IRGEN_RESILIENTTYPEINFO_H
#define SWIFT_IRGEN_RESILIENTTYPEINFO_H
#include "NonFixedTypeInfo.h"
namespace swift {
namespace irgen {
/// An abstract CRTP class designed for types whose values are manipulated
/// indirectly through value witness functions.
///
/// We build upon WitnessSizedTypeInfo, adding the additional structure
/// that the opaque value has the same size as the underlying type with
/// no additional metadata, distinguishing this case from other uses of
/// WitnessSizedTypeInfo, which are existentials (these add conformance
/// tables) and fragile enums with generic payloads (these add tag bits).
///
/// This allows us to make use of array value witness functions, and
/// more importantly, to forward extra inhabitant information from the
/// concrete type. This ensures that enums have the correct layout
/// when accessed at different abstraction levels or from different
/// resilience scopes.
///
template <class Impl>
class ResilientTypeInfo : public WitnessSizedTypeInfo<Impl> {
protected:
ResilientTypeInfo(llvm::Type *type)
: WitnessSizedTypeInfo<Impl>(type, Alignment(1),
IsNotPOD, IsNotBitwiseTakable) {}
public:
void assignWithCopy(IRGenFunction &IGF, Address dest, Address src, SILType T,
bool isOutlined) const override {
emitAssignWithCopyCall(IGF, T, dest, src);
}
void assignArrayWithCopyNoAlias(IRGenFunction &IGF, Address dest, Address src,
llvm::Value *count,
SILType T) const override {
emitAssignArrayWithCopyNoAliasCall(IGF, T, dest, src, count);
}
void assignArrayWithCopyFrontToBack(IRGenFunction &IGF, Address dest,
Address src, llvm::Value *count,
SILType T) const override {
emitAssignArrayWithCopyFrontToBackCall(IGF, T, dest, src, count);
}
void assignArrayWithCopyBackToFront(IRGenFunction &IGF, Address dest,
Address src, llvm::Value *count,
SILType T) const override {
emitAssignArrayWithCopyBackToFrontCall(IGF, T, dest, src, count);
}
void assignWithTake(IRGenFunction &IGF, Address dest, Address src, SILType T,
bool isOutlined) const override {
emitAssignWithTakeCall(IGF, T, dest, src);
}
void assignArrayWithTake(IRGenFunction &IGF, Address dest, Address src,
llvm::Value *count, SILType T) const override {
emitAssignArrayWithTakeCall(IGF, T, dest, src, count);
}
Address initializeBufferWithCopyOfBuffer(IRGenFunction &IGF,
Address dest, Address src,
SILType T) const override {
auto addr = emitInitializeBufferWithCopyOfBufferCall(IGF, T, dest, src);
return this->getAddressForPointer(addr);
}
Address initializeBufferWithTakeOfBuffer(IRGenFunction &IGF,
Address dest, Address src,
SILType T) const override {
auto addr = emitInitializeBufferWithTakeOfBufferCall(IGF, T, dest, src);
return this->getAddressForPointer(addr);
}
void initializeWithCopy(IRGenFunction &IGF, Address dest, Address src,
SILType T, bool isOutlined) const override {
emitInitializeWithCopyCall(IGF, T, dest, src);
}
void initializeArrayWithCopy(IRGenFunction &IGF,
Address dest, Address src, llvm::Value *count,
SILType T) const override {
emitInitializeArrayWithCopyCall(IGF, T, dest, src, count);
}
void initializeWithTake(IRGenFunction &IGF, Address dest, Address src,
SILType T, bool isOutlined) const override {
emitInitializeWithTakeCall(IGF, T, dest, src);
}
void initializeArrayWithTakeNoAlias(IRGenFunction &IGF, Address dest,
Address src, llvm::Value *count,
SILType T) const override {
emitInitializeArrayWithTakeNoAliasCall(IGF, T, dest, src, count);
}
void initializeArrayWithTakeFrontToBack(IRGenFunction &IGF,
Address dest, Address src,
llvm::Value *count,
SILType T) const override {
emitInitializeArrayWithTakeFrontToBackCall(IGF, T, dest, src, count);
}
void initializeArrayWithTakeBackToFront(IRGenFunction &IGF,
Address dest, Address src,
llvm::Value *count,
SILType T) const override {
emitInitializeArrayWithTakeBackToFrontCall(IGF, T, dest, src, count);
}
void destroy(IRGenFunction &IGF, Address addr, SILType T,
bool isOutlined) const override {
emitDestroyCall(IGF, T, addr);
}
void destroyArray(IRGenFunction &IGF, Address addr, llvm::Value *count,
SILType T) const override {
emitDestroyArrayCall(IGF, T, addr, count);
}
bool mayHaveExtraInhabitants(IRGenModule &IGM) const override {
return true;
}
llvm::Value *getExtraInhabitantIndex(IRGenFunction &IGF,
Address src,
SILType T) const override {
return emitGetExtraInhabitantIndexCall(IGF, T, src);
}
void storeExtraInhabitant(IRGenFunction &IGF,
llvm::Value *index,
Address dest,
SILType T) const override {
emitStoreExtraInhabitantCall(IGF, T, index, dest);
}
void initializeMetadata(IRGenFunction &IGF,
llvm::Value *metadata,
llvm::Value *vwtable,
SILType T) const override {
// Resilient value types and archetypes always refer to an existing type.
// A witness table should never be independently initialized for one.
llvm_unreachable("initializing value witness table for opaque type?!");
}
llvm::Value *getEnumTagSinglePayload(IRGenFunction &IGF,
llvm::Value *numEmptyCases,
Address enumAddr,
SILType T) const override {
return emitGetEnumTagSinglePayloadCall(IGF, T, numEmptyCases, enumAddr);
}
void storeEnumTagSinglePayload(IRGenFunction &IGF, llvm::Value *whichCase,
llvm::Value *numEmptyCases, Address enumAddr,
SILType T) const override {
emitStoreEnumTagSinglePayloadCall(IGF, T, whichCase, numEmptyCases, enumAddr);
}
void collectArchetypeMetadata(
IRGenFunction &IGF,
llvm::MapVector<CanType, llvm::Value *> &typeToMetadataVec,
SILType T) const override {
if (!T.hasArchetype()) {
return;
}
auto canType = T.getSwiftRValueType();
auto *metadata = IGF.emitTypeMetadataRefForLayout(T);
assert(metadata && "Expected Type Metadata Ref");
typeToMetadataVec.insert(std::make_pair(canType, metadata));
}
};
}
}
#endif