Files
swift-mirror/stdlib/runtime/KnownMetadata.cpp
Jordan Rose 674a03b085 Replace "oneof" with "union"...everywhere.
We haven't fully updated references to union cases, and enums still are not
their own thing yet, but "oneof" is gone. Long live "union"!

Swift SVN r6783
2013-07-31 21:33:33 +00:00

362 lines
14 KiB
C++

//===--- KnownMetadata.cpp - Swift Language ABI Known Metadata Objects ----===//
//
// 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
//
//===----------------------------------------------------------------------===//
//
// Definitions of some builtin metadata objects.
//
//===----------------------------------------------------------------------===//
#include "swift/Runtime/Metadata.h"
#include "swift/Runtime/Alloc.h"
#include <string.h>
using namespace swift;
/// Copy a value from one object to another based on the size in the
/// given type metadata.
OpaqueValue *swift::swift_copyPOD(OpaqueValue *dest, OpaqueValue *src,
const Metadata *type) {
return (OpaqueValue*) memcpy(dest, src, type->getValueWitnesses()->size);
}
/// A function which helpfully does nothing.
static void doNothing(void *ptr, const void *self) {}
/// A projectBuffer implementation which just reinterprets the buffer.
static OpaqueValue *projectBuffer(ValueBuffer *dest, const Metadata *self) {
return reinterpret_cast<OpaqueValue*>(dest);
}
/// A function which does a naive copy.
template <class T> static T *copy(T *dest, T *src, const Metadata *self) {
*dest = *src;
return dest;
}
/// A function which returns back a static metatype.
const Metadata *swift::swift_staticTypeof(OpaqueValue *src,
const Metadata *self) {
return self;
}
// Work around a Xcode 4.5 bug (rdar://12288058) by explicitly
// instantiating this function template at the types we'll need.
#define INSTANTIATE(TYPE) \
template TYPE *copy<TYPE>(TYPE*, TYPE*, const Metadata*);
INSTANTIATE(bool);
INSTANTIATE(uint8_t);
INSTANTIATE(uint16_t);
INSTANTIATE(uint32_t);
INSTANTIATE(uint64_t);
INSTANTIATE(uintptr_t);
#undef INSTANTIATE
#define POD_VALUE_WITNESS_TABLE(TYPE, SIZE) { \
(value_witness_types::destroyBuffer*) &doNothing, \
(value_witness_types::initializeBufferWithCopyOfBuffer*) &copy<TYPE>, \
(value_witness_types::projectBuffer*) &projectBuffer, \
(value_witness_types::deallocateBuffer*) &doNothing, \
(value_witness_types::destroy*) &doNothing, \
(value_witness_types::initializeBufferWithCopy*) &copy<TYPE>, \
(value_witness_types::initializeWithCopy*) &copy<TYPE>, \
(value_witness_types::assignWithCopy*) &copy<TYPE>, \
(value_witness_types::initializeBufferWithTake*) &copy<TYPE>, \
(value_witness_types::initializeWithTake*) &copy<TYPE>, \
(value_witness_types::assignWithTake*) &copy<TYPE>, \
(value_witness_types::allocateBuffer*) &projectBuffer, \
(value_witness_types::typeOf*) &swift_staticTypeof, \
(value_witness_types::size) (SIZE), \
ValueWitnessFlags().withAlignment(SIZE).withPOD(true) \
.withInlineStorage(true), \
(value_witness_types::stride) (SIZE) \
}
const ValueWitnessTable swift::_TWVBi8_ = POD_VALUE_WITNESS_TABLE(uint8_t, 1);
const ValueWitnessTable swift::_TWVBi16_ = POD_VALUE_WITNESS_TABLE(uint16_t, 2);
const ValueWitnessTable swift::_TWVBi32_ = POD_VALUE_WITNESS_TABLE(uint32_t, 4);
const ValueWitnessTable swift::_TWVBi64_ = POD_VALUE_WITNESS_TABLE(uint64_t, 8);
/// A function to initialize a buffer/variable by retaining the given
/// pointer and then assigning it.
static HeapObject **initWithRetain(HeapObject **dest,
HeapObject **src,
const Metadata *self) {
*dest = swift_retain(*src);
return dest;
}
/// A function to destroy a buffer/variable by releasing the value in it.
static void destroyWithRelease(HeapObject **var, const Metadata *self) {
swift_release(*var);
}
/// A function to assign to a variable by copying from an existing one.
static HeapObject **assignWithRetain(HeapObject **dest,
HeapObject **src,
const Metadata *self) {
HeapObject *newValue = swift_retain(*src);
swift_release(*dest);
*dest = newValue;
return dest;
}
/// A function to assign to a variable by taking from an existing one.
static HeapObject **assignWithoutRetain(HeapObject **dest,
HeapObject **src,
const Metadata *self) {
HeapObject *newValue = *src;
swift_release(*dest);
*dest = newValue;
return dest;
}
/// A function to get the dynamic class type of a Swift heap object.
const Metadata *swift::swift_objectTypeof(OpaqueValue *obj,
const Metadata *self) {
auto *heapRef = *reinterpret_cast<HeapObject**>(obj);
auto *classMetadata = static_cast<const ClassMetadata*>(heapRef->metadata);
// If the heap metadata for the object is not a type, give up and return the
// static type.
if (!classMetadata->isTypeMetadata())
return self;
return classMetadata;
}
/// The basic value-witness table for Swift object pointers.
const ValueWitnessTable swift::_TWVBo = {
(value_witness_types::destroyBuffer*) &destroyWithRelease,
(value_witness_types::initializeBufferWithCopyOfBuffer*) &initWithRetain,
(value_witness_types::projectBuffer*) &projectBuffer,
(value_witness_types::deallocateBuffer*) &doNothing,
(value_witness_types::destroy*) &destroyWithRelease,
(value_witness_types::initializeBufferWithCopy*) &initWithRetain,
(value_witness_types::initializeWithCopy*) &initWithRetain,
(value_witness_types::assignWithCopy*) &assignWithRetain,
(value_witness_types::initializeBufferWithTake*) &copy<uintptr_t>,
(value_witness_types::initializeWithTake*) &copy<uintptr_t>,
(value_witness_types::assignWithTake*) &assignWithoutRetain,
(value_witness_types::allocateBuffer*) &projectBuffer,
(value_witness_types::typeOf*) &swift_objectTypeof,
(value_witness_types::size) sizeof(void*),
ValueWitnessFlags().withAlignment(alignof(void*)).withPOD(false)
.withInlineStorage(true),
(value_witness_types::stride) sizeof(void*)
};
/*** Objective-C pointers ****************************************************/
// This section can reasonably be suppressed in builds that don't
// need to support Objective-C.
// ARC entrypoints.
extern "C" void *objc_retain(void *);
extern "C" void objc_release(void *);
// ObjC runtime entrypoints.
extern "C" const void *object_getClass(void *);
/// A function to initialize a buffer/variable by retaining the given
/// pointer and then assigning it.
static void **initWithObjCRetain(void **dest, void **src,
const Metadata *self) {
*dest = objc_retain(*src);
return dest;
}
/// A function to destroy a buffer/variable by releasing the value in it.
static void destroyWithObjCRelease(void **var, const Metadata *self) {
objc_release(*var);
}
/// A function to assign to a variable by copying from an existing one.
static void **assignWithObjCRetain(void **dest, void **src,
const Metadata *self) {
void *newValue = objc_retain(*src);
objc_release(*dest);
*dest = newValue;
return dest;
}
/// A function to assign to a variable by taking from an existing one.
static void **assignWithoutObjCRetain(void **dest, void **src,
const Metadata *self) {
void *newValue = *src;
objc_release(*dest);
*dest = newValue;
return dest;
}
/// A function to get the Swift type metadata wrapper for an ObjC object's
/// dynamic type.
const Metadata *swift::swift_objcTypeof(OpaqueValue *src, const Metadata *self)
{
auto object = *reinterpret_cast<void**>(src);
auto theClass = object_getClass(object);
auto classAsMetadata = reinterpret_cast<const ClassMetadata*>(theClass);
if (classAsMetadata->isTypeMetadata()) return classAsMetadata;
return swift_getObjCClassMetadata(classAsMetadata);
}
/// The basic value-witness table for ObjC object pointers.
const ValueWitnessTable swift::_TWVBO = {
(value_witness_types::destroyBuffer*) &destroyWithObjCRelease,
(value_witness_types::initializeBufferWithCopyOfBuffer*) &initWithObjCRetain,
(value_witness_types::projectBuffer*) &projectBuffer,
(value_witness_types::deallocateBuffer*) &doNothing,
(value_witness_types::destroy*) &destroyWithObjCRelease,
(value_witness_types::initializeBufferWithCopy*) &initWithObjCRetain,
(value_witness_types::initializeWithCopy*) &initWithObjCRetain,
(value_witness_types::assignWithCopy*) &assignWithObjCRetain,
(value_witness_types::initializeBufferWithTake*) &copy<uintptr_t>,
(value_witness_types::initializeWithTake*) &copy<uintptr_t>,
(value_witness_types::assignWithTake*) &assignWithoutObjCRetain,
(value_witness_types::allocateBuffer*) &projectBuffer,
(value_witness_types::typeOf*) &swift_objcTypeof,
(value_witness_types::size) sizeof(void*),
ValueWitnessFlags().withAlignment(alignof(void*)).withPOD(false)
.withInlineStorage(true),
(value_witness_types::stride) sizeof(void*)
};
/*** Functions ***************************************************************/
namespace {
struct Function {
void *FnPtr;
HeapObject *Data;
};
}
// Assert what we consider to be a reasonable property of ValueBuffer.
static_assert(sizeof(Function) <= sizeof(ValueBuffer),
"function values don't fit inline in a value buffer");
static void function_destroy(Function *fn, const Metadata *self) {
swift_release(fn->Data);
}
static Function *function_initWithRetain(Function *dest, Function *src,
const Metadata *self) {
dest->FnPtr = src->FnPtr;
dest->Data = swift_retain(src->Data);
return dest;
}
static Function *function_initWithoutRetain(Function *dest, Function *src,
const Metadata *self) {
dest->FnPtr = src->FnPtr;
dest->Data = src->Data;
return dest;
}
static Function *function_assignWithRetain(Function *dest, Function *src,
const Metadata *self) {
dest->FnPtr = src->FnPtr;
if (dest->Data != src->Data) {
HeapObject *oldData = dest->Data;
dest->Data = swift_retain(src->Data);
swift_release(oldData);
}
return dest;
}
static Function *function_assignWithoutRetain(Function *dest, Function *src,
const Metadata *self) {
dest->FnPtr = src->FnPtr;
HeapObject *oldData = dest->Data;
dest->Data = src->Data;
swift_release(oldData);
return dest;
}
/// The basic value-witness table for function types.
const ValueWitnessTable swift::_TWVFT_T_ = {
(value_witness_types::destroyBuffer*) &function_destroy,
(value_witness_types::initializeBufferWithCopyOfBuffer*) &function_initWithRetain,
(value_witness_types::projectBuffer*) &projectBuffer,
(value_witness_types::deallocateBuffer*) &doNothing,
(value_witness_types::destroy*) &function_destroy,
(value_witness_types::initializeBufferWithCopy*) &function_initWithRetain,
(value_witness_types::initializeWithCopy*) &function_initWithRetain,
(value_witness_types::assignWithCopy*) &function_assignWithRetain,
(value_witness_types::initializeBufferWithTake*) &function_initWithoutRetain,
(value_witness_types::initializeWithTake*) &function_initWithoutRetain,
(value_witness_types::assignWithTake*) &function_assignWithoutRetain,
(value_witness_types::allocateBuffer*) &projectBuffer,
(value_witness_types::typeOf*) &swift_staticTypeof,
(value_witness_types::size) sizeof(Function),
ValueWitnessFlags().withAlignment(alignof(Function)).withPOD(false)
.withInlineStorage(true),
(value_witness_types::stride) sizeof(Function)
};
/*** Empty tuples ************************************************************/
// A function which does nothing and returns its first argument.
static void *doNothing3(void *dest, void *src, void *self) {
return dest;
}
/// The basic value-witness table for empty types.
const ValueWitnessTable swift::_TWVT_ = {
(value_witness_types::destroyBuffer*) &doNothing,
(value_witness_types::initializeBufferWithCopyOfBuffer*) &doNothing3,
(value_witness_types::projectBuffer*) &projectBuffer,
(value_witness_types::deallocateBuffer*) &doNothing,
(value_witness_types::destroy*) &doNothing,
(value_witness_types::initializeBufferWithCopy*) &doNothing3,
(value_witness_types::initializeWithCopy*) &doNothing3,
(value_witness_types::assignWithCopy*) &doNothing3,
(value_witness_types::initializeBufferWithTake*) &doNothing3,
(value_witness_types::initializeWithTake*) &doNothing3,
(value_witness_types::assignWithTake*) &doNothing3,
(value_witness_types::allocateBuffer*) &projectBuffer,
(value_witness_types::typeOf*) &swift_staticTypeof,
(value_witness_types::size) 0,
ValueWitnessFlags().withAlignment(1).withPOD(true).withInlineStorage(true),
(value_witness_types::stride) 0
};
/*** Bool ********************************************************************/
// FIXME: The compiler should generate this.
const ValueWitnessTable swift::_TWVSb = POD_VALUE_WITNESS_TABLE(bool, 1);
/*** Known metadata **********************************************************/
// Define some builtin opaque metadata.
#define OPAQUE_METADATA(TYPE) \
const FullOpaqueMetadata swift::_TMd##TYPE = { \
{ &_TWV##TYPE }, \
{ { MetadataKind::Opaque } } \
};
OPAQUE_METADATA(Bi8_)
OPAQUE_METADATA(Bi16_)
OPAQUE_METADATA(Bi32_)
OPAQUE_METADATA(Bi64_)
OPAQUE_METADATA(Bo)
OPAQUE_METADATA(BO)
// FIXME: The compiler should generate Union metadata for Bool.
OPAQUE_METADATA(Sb)
/// The standard metadata for the empty tuple.
const FullMetadata<TupleTypeMetadata> swift::_TMdT_ = {
{ &_TWVT_ }, // ValueWitnesses
{
{ MetadataKind::Tuple }, // Kind
0, // NumElements
nullptr // Labels
}
};