//===--- ErrorObject.cpp - Recoverable error object -----------------------===// // // This source file is part of the Swift.org open source project // // Copyright (c) 2014 - 2016 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 // //===----------------------------------------------------------------------===// // // This implements the object representation of the standard ErrorProtocol // protocol type, which represents recoverable errors in the language. This // implementation is used when ObjC interop is disabled; the ObjC-interoperable // version is implemented in ErrorObject.mm. // //===----------------------------------------------------------------------===// #include #include "swift/Runtime/Debug.h" #include "ErrorObject.h" #include "Private.h" #if !SWIFT_OBJC_INTEROP using namespace swift; /// Determine the size and alignment of an ErrorProtocol box containing the given /// type. static std::pair _getErrorAllocatedSizeAndAlignmentMask(const Metadata *type) { // The value is tail-allocated after the SwiftError record with the // appropriate alignment. auto vw = type->getValueWitnesses(); size_t size = sizeof(SwiftError); unsigned valueAlignMask = vw->getAlignmentMask(); size = (size + valueAlignMask) & ~(size_t)valueAlignMask; size += vw->getSize(); size_t alignMask = (alignof(SwiftError) - 1) | valueAlignMask; return {size, alignMask}; } /// Destructor for an ErrorProtocol box. static void _destroyErrorObject(HeapObject *obj) { auto error = static_cast(obj); // Destroy the value inside. auto type = error->type; type->vw_destroy(error->getValue()); // Deallocate the buffer. auto sizeAndAlign = _getErrorAllocatedSizeAndAlignmentMask(type); swift_deallocObject(obj, sizeAndAlign.first, sizeAndAlign.second); } /// Heap metadata for ErrorProtocol boxes. static const FullMetadata ErrorProtocolMetadata{ HeapMetadataHeader{{_destroyErrorObject}, {&_TWVBo}}, Metadata{MetadataKind::ErrorObject}, }; SWIFT_CC(swift) SWIFT_RUNTIME_EXPORT extern "C" BoxPair::Return swift::swift_allocError(const swift::Metadata *type, const swift::WitnessTable *errorConformance, OpaqueValue *initialValue, bool isTake) { auto sizeAndAlign = _getErrorAllocatedSizeAndAlignmentMask(type); auto allocated = swift_allocObject(&ErrorProtocolMetadata, sizeAndAlign.first, sizeAndAlign.second); auto error = reinterpret_cast(allocated); error->type = type; error->errorConformance = errorConformance; // If an initial value was given, copy or take it in. auto valuePtr = error->getValue(); if (initialValue) { if (isTake) type->vw_initializeWithTake(valuePtr, initialValue); else type->vw_initializeWithCopy(valuePtr, initialValue); } return BoxPair{allocated, valuePtr}; } void swift::swift_deallocError(SwiftError *error, const Metadata *type) { auto sizeAndAlign = _getErrorAllocatedSizeAndAlignmentMask(type); swift_deallocObject(error, sizeAndAlign.first, sizeAndAlign.second); } void swift::swift_getErrorValue(const SwiftError *errorObject, void **scratch, ErrorValueResult *out) { out->value = errorObject->getValue(); out->type = errorObject->type; out->errorConformance = errorObject->errorConformance; } void swift::swift_willThrow(SwiftError *object) { } #endif