//===--- ErrorObjectNative.cpp - Recoverable error object -----------------===// // // 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 implements the object representation of the standard Error // 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 "swift/Runtime/Config.h" #if !SWIFT_OBJC_INTEROP #include #include "swift/Runtime/Debug.h" #include "ErrorObject.h" #include "Private.h" using namespace swift; /// Determine the size and alignment of an Error 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 Error box. static SWIFT_CC(swift) void _destroyErrorObject(SWIFT_CONTEXT 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 Error boxes. static const FullMetadata ErrorMetadata{ HeapMetadataHeader{{_destroyErrorObject}, {&VALUE_WITNESS_SYM(Bo)}}, HeapMetadata(MetadataKind::ErrorObject), }; BoxPair swift::swift_allocError(const swift::Metadata *type, const swift::WitnessTable *errorConformance, OpaqueValue *initialValue, bool isTake) { auto sizeAndAlign = _getErrorAllocatedSizeAndAlignmentMask(type); auto allocated = swift_allocObject(&ErrorMetadata, 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; } /// Breakpoint hook for debuggers. SWIFT_CC(swift) void swift::swift_willThrow(SWIFT_CONTEXT void *unused, SWIFT_ERROR_RESULT SwiftError **error) { // do nothing } #endif