blob: c765c36cfae8e7f9206eb8074c567fee346e53ea [file] [log] [blame]
//===--- 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 <stdio.h>
#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<size_t, size_t>
_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<SwiftError *>(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<HeapMetadata> 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<SwiftError*>(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_deallocUninitializedObject(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