Getting started on matching a thrown exception to a catch clause, and setting the adjusted pointer to the caught object appearing in the catch clause.

llvm-svn: 148666
This commit is contained in:
Howard Hinnant 2012-01-22 21:47:40 +00:00
parent e197d943f3
commit 699692a04c
3 changed files with 53 additions and 8 deletions

View File

@ -14,6 +14,7 @@
#include "unwind.h"
#include "cxa_exception.hpp"
#include "private_typeinfo.h"
#include <typeinfo>
#include <stdlib.h>
#include <assert.h>
@ -219,6 +220,8 @@ getTTypeEntry(int64_t typeOffset, const uint8_t* classInfo, uint8_t ttypeEncodin
return classInfo - typeOffset;
}
static const uint64_t kOurDependentExceptionClass = 0x434C4E47432B2B01; // CLNGC++\1
/// Deals with Dwarf actions matching our type infos
/// (OurExceptionType_t instances). Returns whether or not a dwarf emitted
/// action matches the supplied exception type. If such a match succeeds,
@ -240,7 +243,12 @@ handleActionValue(const uint8_t* classInfo, uintptr_t actionEntry,
_Unwind_Exception* unwind_exception, uint8_t ttypeEncoding)
{
__cxa_exception* exception_header = (__cxa_exception*)(unwind_exception+1) - 1;
const std::type_info* excpType = exception_header->exceptionType;
void* thrown_object =
unwind_exception->exception_class == kOurDependentExceptionClass ?
((__cxa_dependent_exception*)exception_header)->primaryException :
exception_header + 1;
const __shim_type_info* excpType =
static_cast<const __shim_type_info*>(exception_header->exceptionType);
const uint8_t* actionPos = (uint8_t*)actionEntry;
while (true)
{
@ -255,14 +263,17 @@ handleActionValue(const uint8_t* classInfo, uintptr_t actionEntry,
{
const uint8_t* TTypeEntry = getTTypeEntry(typeOffset, classInfo,
ttypeEncoding);
const std::type_info* catchType =
(const std::type_info*)readEncodedPointer(&TTypeEntry,
const __shim_type_info* catchType =
(const __shim_type_info*)readEncodedPointer(&TTypeEntry,
ttypeEncoding);
void* adjustedPtr = thrown_object;
// catchType == 0 -> catch (...)
if (catchType == 0 || excpType == catchType)
if (catchType == 0 || catchType->can_catch(excpType, adjustedPtr))
{
exception_header->handlerSwitchValue = typeOffset;
exception_header->actionRecord = SactionPos;
exception_header->actionRecord = SactionPos; // unnecessary?
// used by __cxa_get_exception_ptr and __cxa_begin_catch
exception_header->adjustedPtr = adjustedPtr;
return true;
}
}
@ -289,9 +300,6 @@ contains_handler(_Unwind_Exception* unwind_exception, _Unwind_Context* context)
__cxa_exception* exception_header = (__cxa_exception*)(unwind_exception+1) - 1;
const uint8_t* lsda = (const uint8_t*)_Unwind_GetLanguageSpecificData(context);
exception_header->languageSpecificData = lsda;
// set adjustedPtr! __cxa_get_exception_ptr and __cxa_begin_catch use it.
// TODO: Put it where it is supposed to be and adjust it properly
exception_header->adjustedPtr = unwind_exception+1;
if (lsda)
{
// Get the current instruction pointer and offset it before next

View File

@ -198,6 +198,42 @@ __pointer_to_member_type_info::display() const
__pointee->display();
}
// can_catch
// A handler is a match for an exception object of type E if
// * The handler is of type cv T or cv T& and E and T are the same type
// (ignoring the top-level cv-qualifiers), or
// * the handler is of type cv T or cv T& and T is an unambiguous public
// base class of E, or
// * the handler is of type cv1 T* cv2 and E is a pointer type that can be
// converted to the type of the handler by either or both of
// * a standard pointer conversion (4.10) not involving conversions to
// pointers to private or protected or ambiguous classes
// * a qualification conversion
// * the handler is a pointer or pointer to member type and E is std::nullptr_t.
// adjustedPtr:
//
// catch (A& a) : adjustedPtr == &a
// catch (A* a) : adjustedPtr == a
// catch (A** a) : adjustedPtr == a
//
// catch (D2& d2) : adjustedPtr == &d2 (d2 is base class of thrown object)
// catch (D2* d2) : adjustedPtr == d2
// catch (D2*& d2) : adjustedPtr == d2
//
// catch (...) : adjustedPtr == & of the exception
// TODO: can_catch looks similar to search_above_dst. Reuse?
bool
__shim_type_info::can_catch(const __shim_type_info* thrown_type,
void*&) const
{
return this == thrown_type;
}
#pragma GCC visibility pop
#pragma GCC visibility push(default)

View File

@ -24,6 +24,7 @@ class __shim_type_info
public:
virtual ~__shim_type_info();
virtual bool can_catch(const __shim_type_info* thrown_type, void*& adjustedPtr) const;
virtual void display() const = 0;
};