diff options
Diffstat (limited to 'compiler_and_linker/unsorted/CException.c')
-rw-r--r-- | compiler_and_linker/unsorted/CException.c | 2183 |
1 files changed, 0 insertions, 2183 deletions
diff --git a/compiler_and_linker/unsorted/CException.c b/compiler_and_linker/unsorted/CException.c deleted file mode 100644 index d68ce13..0000000 --- a/compiler_and_linker/unsorted/CException.c +++ /dev/null @@ -1,2183 +0,0 @@ -#include "compiler/CException.h" -#include "compiler/CABI.h" -#include "compiler/CClass.h" -#include "compiler/CDecl.h" -#include "compiler/CError.h" -#include "compiler/CExpr.h" -#include "compiler/CFunc.h" -#include "compiler/CInline.h" -#include "compiler/CInit.h" -#include "compiler/CMachine.h" -#include "compiler/CMangler.h" -#include "compiler/CParser.h" -#include "compiler/CPrep.h" -#include "compiler/CPrepTokenizer.h" -#include "compiler/CScope.h" -#include "compiler/CompilerTools.h" -#include "compiler/Exceptions.h" -#include "compiler/objects.h" -#include "compiler/scopes.h" -#include "compiler/types.h" - -typedef struct UniqueObj { - struct UniqueObj *next; - Object *object; - SInt32 uniqueid; -} UniqueObj; - -ExceptionAction *cexcept_dobjstack; -Boolean cexcept_hasdobjects; -Boolean cexcept_magic; -static UniqueObj *cexcept_uniqueobjs; -static Boolean cexcept_canthrow; -static DtorTemp *cexcept_dtortemps; -static Statement *cexcept_prevstmt; -static ExceptionAction *cexcept_eabefore; -static ExceptionAction *cexcept_eaafter; -static Boolean cexcept_expandtrycatch; -static Boolean cexcept_hastrycatch; -static Boolean cexcept_serialize; - -// forward decls -static ENode *CExcept_TempTransExprCond(ENode *expr); -static ENode *CExcept_TempTransExpr(ENode *expr); - -void CExcept_Setup(void) { - cexcept_dobjstack = NULL; - cexcept_uniqueobjs = NULL; - cexcept_hasdobjects = 0; - cexcept_magic = 0; -} - -Boolean CExcept_CanThrowException(Object *object, Boolean flag) { - if (copts.optEH && IS_TYPE_FUNC(object->type)) { - if (flag) - return 1; - - if (TYPE_FUNC(object->type)->flags & FUNC_NOTHROW) - return 0; - - if ( - !flag && - TYPE_FUNC(object->type)->exspecs && - TYPE_FUNC(object->type)->exspecs && - !TYPE_FUNC(object->type)->exspecs->type - ) - return 0; - - if ( - copts.optEH2 && - !(object->qual & Q_MANGLE_NAME) && - object != rt_ptmf_call && - object != rt_ptmf_scall && - object != Rdync_func && - object != rt_som_glue1 && - object != rt_som_glue2 && - object != rt_som_glue3 && - object != carr_func && - object != cnar_func && - object != darr_func && - object != dnar_func && - object != dnar3_func && - object != Xthrw_func - ) - return 0; - } - - return 1; -} - -void CExcept_CheckStackRefs(ExceptionAction *actions) { - while (actions) { - switch (actions->type) { - case EAT_DESTROYLOCAL: - CInline_ObjectAddrRef(actions->data.destroy_local.dtor); - break; - case EAT_DESTROYLOCALCOND: - CInline_ObjectAddrRef(actions->data.destroy_local_cond.dtor); - break; - case EAT_DESTROYLOCALOFFSET: - CInline_ObjectAddrRef(actions->data.destroy_local_offset.dtor); - break; - case EAT_DESTROYLOCALPOINTER: - CInline_ObjectAddrRef(actions->data.destroy_local_pointer.dtor); - break; - case EAT_DESTROYLOCALARRAY: - CInline_ObjectAddrRef(actions->data.destroy_local_array.dtor); - break; - case EAT_DESTROYPARTIALARRAY: - CInline_ObjectAddrRef(actions->data.destroy_partial_array.dtor); - break; - case EAT_DESTROYMEMBER: - case EAT_DESTROYBASE: - CInline_ObjectAddrRef(actions->data.destroy_member.dtor); - break; - case EAT_DESTROYMEMBERCOND: - CInline_ObjectAddrRef(actions->data.destroy_member_cond.dtor); - break; - case EAT_DESTROYMEMBERARRAY: - CInline_ObjectAddrRef(actions->data.destroy_member_array.dtor); - break; - case EAT_DELETEPOINTER: - case EAT_DELETELOCALPOINTER: - CInline_ObjectAddrRef(actions->data.delete_pointer.deletefunc); - break; - case EAT_DELETEPOINTERCOND: - CInline_ObjectAddrRef(actions->data.delete_pointer_cond.deletefunc); - break; - case EAT_CATCHBLOCK: - case EAT_ACTIVECATCHBLOCK: - case EAT_SPECIFICATION: - case EAT_TERMINATE: - break; - default: - CError_FATAL(192); - } - actions = actions->prev; - } -} - -void CExcept_CompareSpecifications(ExceptSpecList *a, ExceptSpecList *b) { - ExceptSpecList *aa; - ExceptSpecList *bb; - - aa = a; - bb = b; - while (1) { - if (!aa) { - if (!bb) - break; - CError_Error(CErrorStr265); - return; - } - - if (!bb) { - CError_Error(CErrorStr265); - return; - } - - aa = aa->next; - bb = bb->next; - } - - if (a->type == NULL) { - if (b->type != NULL) - CError_Error(CErrorStr265); - } else if (b->type == NULL) { - CError_Error(CErrorStr265); - } else { - for (aa = a; aa; aa = aa->next) { - for (bb = b; bb; bb = bb->next) { - if (is_typesame(aa->type, bb->type) && aa->qual == bb->qual) - break; - } - - if (bb == NULL) { - CError_Error(CErrorStr265); - return; - } - } - } -} - -Boolean CExcept_ActionCompare(ExceptionAction *a, ExceptionAction *b) { - if (a->type == b->type) { - switch (a->type) { - case EAT_DESTROYLOCAL: - return a->data.destroy_local.local == b->data.destroy_local.local; - case EAT_DESTROYLOCALCOND: - return a->data.destroy_local_cond.local == b->data.destroy_local_cond.local; - case EAT_DESTROYLOCALOFFSET: - return a->data.destroy_local_offset.local == b->data.destroy_local_offset.local && - a->data.destroy_local_offset.offset == b->data.destroy_local_offset.offset; - case EAT_DESTROYLOCALPOINTER: - return a->data.destroy_local_pointer.pointer == b->data.destroy_local_pointer.pointer; - case EAT_DESTROYLOCALARRAY: - return a->data.destroy_local_array.localarray == b->data.destroy_local_array.localarray; - case EAT_DESTROYPARTIALARRAY: - return a->data.destroy_partial_array.arraypointer == b->data.destroy_partial_array.arraypointer; - case EAT_DESTROYMEMBER: - case EAT_DESTROYBASE: - return a->data.destroy_member.objectptr == b->data.destroy_member.objectptr && - a->data.destroy_member.offset == b->data.destroy_member.offset; - case EAT_DESTROYMEMBERCOND: - return a->data.destroy_member_cond.objectptr == b->data.destroy_member_cond.objectptr && - a->data.destroy_member_cond.offset == b->data.destroy_member_cond.offset; - case EAT_DESTROYMEMBERARRAY: - return a->data.destroy_member_array.objectptr == b->data.destroy_member_array.objectptr && - a->data.destroy_member_array.offset == b->data.destroy_member_array.offset; - case EAT_DELETEPOINTER: - case EAT_DELETELOCALPOINTER: - return a->data.delete_pointer.pointerobject == b->data.delete_pointer.pointerobject && - a->data.delete_pointer.deletefunc == b->data.delete_pointer.deletefunc; - case EAT_DELETEPOINTERCOND: - return a->data.delete_pointer_cond.cond == b->data.delete_pointer_cond.cond; - case EAT_CATCHBLOCK: - return a->data.catch_block.catch_label == b->data.catch_block.catch_label; - case EAT_ACTIVECATCHBLOCK: - return a->data.active_catch_block.catch_info_object == b->data.active_catch_block.catch_info_object; - case EAT_TERMINATE: - return 1; - case EAT_SPECIFICATION: - return a->data.specification.unexp_id == b->data.specification.unexp_id; - default: - CError_FATAL(314); - } - } - - return 0; -} - -int CExcept_IsSubList(ExceptionAction *a, ExceptionAction *b) { - int diff; - int i; - int count1; - int count2; - ExceptionAction *scan; - - if (a == b) - return 0; - - count1 = 0; - scan = a; - while (scan) { - scan = scan->prev; - count1++; - } - - scan = b; - count2 = 0; - while (scan) { - scan = scan->prev; - count2++; - } - - diff = count2 - count1; - if (diff < 0) - return -1; - - for (i = 0; i < diff; i++) - b = b->prev; - - while (a != b) { - if (!a || !b || !CExcept_ActionCompare(a, b)) - return -1; - a = a->prev; - b = b->prev; - } - - return diff; -} - -Boolean CExcept_ActionNeedsDestruction(ExceptionAction *action) { - switch (action->type) { - case EAT_CATCHBLOCK: - return 0; - case EAT_DESTROYLOCAL: - case EAT_DESTROYLOCALOFFSET: - case EAT_DESTROYLOCALARRAY: - case EAT_DELETELOCALPOINTER: - case EAT_ACTIVECATCHBLOCK: - return 1; - case EAT_NOP: - case EAT_DESTROYMEMBER: - case EAT_DESTROYMEMBERCOND: - case EAT_DESTROYMEMBERARRAY: - case EAT_DESTROYBASE: - break; - default: - CError_FATAL(363); - } - - return 0; -} - -ENode *CExcept_RegisterDestructorObject(Object *local, SInt32 offset, Object *dtor, Boolean flag) { - ExceptionAction *action; - ENode *expr; - Object *dtorObject; - - action = lalloc(sizeof(ExceptionAction)); - memclrw(action, sizeof(ExceptionAction)); - - action->prev = cexcept_dobjstack; - cexcept_dobjstack = action; - - expr = create_objectrefnode(local); - dtorObject = CABI_GetDestructorObject(dtor, CABIDestroy1); - - if (offset == 0) { - action->type = EAT_DESTROYLOCAL; - action->data.destroy_local.local = local; - action->data.destroy_local.dtor = dtorObject; - } else { - action->type = EAT_DESTROYLOCALOFFSET; - action->data.destroy_local_offset.local = local; - action->data.destroy_local_offset.dtor = dtorObject; - action->data.destroy_local_offset.offset = offset; - expr = makediadicnode(expr, intconstnode(TYPE(&stunsignedlong), offset), EADD); - } - - cexcept_hasdobjects = 1; - return expr; -} - -void CExcept_RegisterLocalArray(Statement *stmt, Object *localarray, Object *dtor, SInt32 elements, SInt32 element_size) { - ExceptionAction *action; - Object *dtorObject; - - action = lalloc(sizeof(ExceptionAction)); - memclrw(action, sizeof(ExceptionAction)); - - action->prev = cexcept_dobjstack; - cexcept_dobjstack = action; - - dtorObject = CABI_GetDestructorObject(dtor, CABIDestroy1); - - action->type = EAT_DESTROYLOCALARRAY; - action->data.destroy_local_array.localarray = localarray; - action->data.destroy_local_array.dtor = dtorObject; - action->data.destroy_local_array.elements = elements; - action->data.destroy_local_array.element_size = element_size; - - cexcept_hasdobjects = 1; -} - -void CExcept_RegisterDeleteObject(Statement *stmt, Object *pointerobject, Object *deletefunc) { - ExceptionAction *action; - - action = lalloc(sizeof(ExceptionAction)); - memclrw(action, sizeof(ExceptionAction)); - - action->prev = cexcept_dobjstack; - cexcept_dobjstack = action; - - action->type = EAT_DELETELOCALPOINTER; - action->data.delete_pointer.pointerobject = pointerobject; - action->data.delete_pointer.deletefunc = deletefunc; - - cexcept_hasdobjects = 1; -} - -static void CExcept_PatchConstructorAction(Statement *stmt, ExceptionAction *actionArg) { - ExceptionAction *action30; - ExceptionAction *action; - ExceptionAction *scan; - - for (action = stmt->dobjstack; action; action = action->prev) { - switch (action->type) { - case EAT_DESTROYMEMBER: - case EAT_DESTROYMEMBERCOND: - case EAT_DESTROYMEMBERARRAY: - case EAT_SPECIFICATION: - case EAT_DESTROYBASE: - goto exitFirstLoop; - case EAT_CATCHBLOCK: - action30 = action; - while (1) { - if (!action30->prev) - goto exitFirstLoop; - action30 = action30->prev; - if (action30->type != EAT_CATCHBLOCK) { - CError_FATAL(481); - } - } - } - } - exitFirstLoop: - if (action == NULL) { - while (stmt) { - if ((scan = stmt->dobjstack)) { - while (1) { - if (scan == actionArg) - break; - if (scan->prev == NULL) { - scan->prev = actionArg; - break; - } - scan = scan->prev; - } - } else { - stmt->dobjstack = actionArg; - } - stmt = stmt->next; - } - } else { - actionArg->prev = action; - while (stmt) { - if (stmt->dobjstack != action) { - scan = stmt->dobjstack; - do { - if (scan == actionArg) - goto nextStmt; - if (scan->prev == action) { - scan->prev = actionArg; - goto nextStmt; - } - } while ((scan = scan->prev)); - - while (1) { - if (action->type == EAT_CATCHBLOCK && action->prev == NULL) - return; - - action = action->prev; - if (!action) - CError_FATAL(531); - } - } else { - stmt->dobjstack = actionArg; - } - nextStmt: - stmt = stmt->next; - } - } -} - -void CExcept_Terminate(void) { - ExceptionAction *action; - - action = lalloc(sizeof(ExceptionAction)); - memclrw(action, sizeof(ExceptionAction)); - - action->type = EAT_TERMINATE; - - action->prev = cexcept_dobjstack; - cexcept_dobjstack = action; -} - -void CExcept_Magic(void) { - cexcept_magic = 1; -} - -static Object *CExcept_FindLocalObject(char *name) { - NameResult result; - NameSpaceObjectList *list; - - list = CScope_FindObjectList(&result, GetHashNameNodeExport(name)); - if (list && list->object->otype == OT_OBJECT && OBJECT(list->object)->datatype == DLOCAL) - return OBJECT(list->object); - - CError_FATAL(580); - return NULL; -} - -void CExcept_ArrayInit(void) { - ExceptionAction *action; - - action = lalloc(sizeof(ExceptionAction)); - memclrw(action, sizeof(ExceptionAction)); - - action->type = EAT_DESTROYPARTIALARRAY; - action->data.destroy_partial_array.arraypointer = CExcept_FindLocalObject("ptr"); - action->data.destroy_partial_array.arraycounter = CExcept_FindLocalObject("i"); - action->data.destroy_partial_array.dtor = CExcept_FindLocalObject("dtor"); - action->data.destroy_partial_array.element_size = CExcept_FindLocalObject("size"); - - action->prev = cexcept_dobjstack; - cexcept_dobjstack = action; -} - -void CExcept_RegisterMember(Statement *stmt, Object *objectptr, SInt32 offset, Object *dtor, Object *cond, Boolean isMember) { - ExceptionAction *action; - - action = lalloc(sizeof(ExceptionAction)); - memclrw(action, sizeof(ExceptionAction)); - - if (cond == NULL) { - if (isMember) { - action->type = EAT_DESTROYMEMBER; - action->data.destroy_member.dtor = CABI_GetDestructorObject(dtor, CABIDestroy1); - } else { - action->type = EAT_DESTROYBASE; - action->data.destroy_member.dtor = CABI_GetDestructorObject(dtor, CABIDestroy0); - } - action->data.destroy_member.objectptr = objectptr; - action->data.destroy_member.offset = offset; - } else { - CError_ASSERT(632, cond->type == TYPE(&stsignedshort)); - action->type = EAT_DESTROYMEMBERCOND; - action->data.destroy_member_cond.objectptr = objectptr; - action->data.destroy_member_cond.cond = cond; - action->data.destroy_member_cond.dtor = CABI_GetDestructorObject(dtor, CABIDestroy1); - action->data.destroy_member_cond.offset = offset; - } - - CExcept_PatchConstructorAction(stmt, action); - stmt->flags |= StmtFlag_2; -} - -void CExcept_RegisterMemberArray(Statement *stmt, Object *objectptr, SInt32 offset, Object *dtor, SInt32 elements, SInt32 element_size) { - ExceptionAction *action; - - action = lalloc(sizeof(ExceptionAction)); - memclrw(action, sizeof(ExceptionAction)); - - action->type = EAT_DESTROYMEMBERARRAY; - action->data.destroy_member_array.objectptr = objectptr; - action->data.destroy_member_array.dtor = CABI_GetDestructorObject(dtor, CABIDestroy1); - action->data.destroy_member_array.offset = offset; - action->data.destroy_member_array.elements = elements; - action->data.destroy_member_array.element_size = element_size; - - CExcept_PatchConstructorAction(stmt, action); - stmt->flags |= StmtFlag_2; -} - -static Statement *CExcept_DestroyLocal(ExceptionAction *ea, Statement *stmt, Object *object, Object *dtor, SInt32 offset) { - ENode *expr; - - expr = create_objectrefnode(object); - if (offset) - expr = makediadicnode(expr, intconstnode(TYPE(&stunsignedlong), offset), EADD); - - expr = CABI_DestroyObject(dtor, expr, CABIDestroy1, 1, 0); - - CError_ASSERT(687, expr->type == EFUNCCALL && expr->data.funccall.funcref->type == EOBJREF); - if (expr->data.funccall.funcref->data.objref->datatype == DVFUNC) - expr->data.funccall.funcref->flags |= ENODE_FLAG_80; - - stmt = CFunc_InsertStatement(ST_EXPRESSION, stmt); - stmt->expr = expr; - stmt->dobjstack = ea->prev; - return stmt; -} - -static Statement *CExcept_DestroyLocalPointer(ExceptionAction *ea, Statement *stmt, Object *object, Object *deletefunc) { - Statement *newStmt; - - newStmt = CFunc_InsertStatement(ST_EXPRESSION, stmt); - newStmt->expr = funccallexpr(deletefunc, create_objectnode2(object), NULL, NULL, NULL); - newStmt->dobjstack = ea->prev; - return newStmt; -} - -static Statement *CExcept_DestroyLocalArray(ExceptionAction *ea, Statement *stmt, Object *object, Object *dtor, SInt32 elements, SInt32 element_size) { - Statement *newStmt; - ENode *dtorExpr; - - newStmt = CFunc_InsertStatement(ST_EXPRESSION, stmt); - - if (dtor) - dtorExpr = create_objectrefnode(CABI_GetDestructorObject(dtor, CABIDestroy1)); - else - dtorExpr = nullnode(); - - newStmt->expr = funccallexpr( - darr_func, - create_objectrefnode(object), - dtorExpr, - intconstnode(TYPE(&stunsignedlong), element_size), - intconstnode(TYPE(&stunsignedlong), elements) - ); - - newStmt->dobjstack = ea->prev; - return newStmt; -} - -static Statement *CExcept_EndCatch(ExceptionAction *ea, Statement *stmt) { - stmt = CFunc_InsertStatement(ST_ENDCATCHDTOR, stmt); - stmt->expr = create_objectrefnode(ea->data.active_catch_block.catch_info_object); - stmt->dobjstack = ea->prev; - if (!ea->data.active_catch_block.call_dtor) - stmt->type = ST_ENDCATCH; - return stmt; -} - -Statement *CExcept_ActionCleanup(ExceptionAction *ea, Statement *stmt) { - switch (ea->type) { - case EAT_DESTROYLOCALCOND: - case EAT_DESTROYLOCALPOINTER: - case EAT_DESTROYPARTIALARRAY: - case EAT_DESTROYMEMBER: - case EAT_DESTROYMEMBERCOND: - case EAT_DESTROYMEMBERARRAY: - case EAT_DELETEPOINTER: - case EAT_DELETEPOINTERCOND: - case EAT_CATCHBLOCK: - case EAT_SPECIFICATION: - case EAT_TERMINATE: - case EAT_DESTROYBASE: - break; - case EAT_DESTROYLOCAL: - stmt = CExcept_DestroyLocal( - ea, stmt, - ea->data.destroy_local.local, - ea->data.destroy_local.dtor, - 0); - break; - case EAT_DESTROYLOCALOFFSET: - stmt = CExcept_DestroyLocal( - ea, stmt, - ea->data.destroy_local.local, - ea->data.destroy_local.dtor, - ea->data.destroy_local_offset.offset); - break; - case EAT_DELETELOCALPOINTER: - stmt = CExcept_DestroyLocalPointer( - ea, stmt, - ea->data.delete_pointer.pointerobject, - ea->data.delete_pointer.deletefunc); - break; - case EAT_DESTROYLOCALARRAY: - stmt = CExcept_DestroyLocalArray( - ea, stmt, - ea->data.destroy_local_array.localarray, - ea->data.destroy_local_array.dtor, - ea->data.destroy_local_array.elements, - ea->data.destroy_local_array.element_size); - break; - case EAT_ACTIVECATCHBLOCK: - stmt = CExcept_EndCatch(ea, stmt); - break; - default: - CError_FATAL(827); - } - - return stmt; -} - -static void CExcept_MangleNameSpaceName(NameSpace *nspace) { - while (nspace) { - if (nspace->name) { - CExcept_MangleNameSpaceName(nspace->parent); - AppendGListName(&name_mangle_list, nspace->name->name); - AppendGListName(&name_mangle_list, "::"); - break; - } - nspace = nspace->parent; - } -} - -static void CExcept_MangleClassName(TypeClass *tclass) { - NameSpace *nspace; - char buf[64]; - - CExcept_MangleNameSpaceName(tclass->nspace->parent); - AppendGListName(&name_mangle_list, tclass->classname->name); - - for (nspace = tclass->nspace->parent; nspace; nspace = nspace->parent) { - if (!nspace->is_global && !nspace->is_templ && !nspace->name) { - CError_ASSERT(868, cscope_currentfunc != NULL); - - sprintf(buf, "*%" PRIxPTR "*%" PRIxPTR "*", &cscope_currentfunc, &nspace); - AppendGListName(&name_mangle_list, buf); - break; - } - } -} - -typedef struct BCL { - struct BCL *next; - TypeClass *tclass; - SInt32 offset; - Boolean is_virtual; - Boolean is_public; - Boolean is_ambig; -} BCL; - -static void CExcept_MakeBaseClassListAmbig(BCL *bcl, TypeClass *tclass) { - BCL *scan; - ClassList *list; - - for (scan = bcl; scan; scan = scan->next) { - if (scan->tclass == tclass) - scan->is_ambig = 1; - } - - for (list = tclass->bases; list; list = list->next) - CExcept_MakeBaseClassListAmbig(bcl, list->base); -} - -static BCL *CExcept_GetBaseClassList(BCL *bcl, TypeClass *tclass1, TypeClass *tclass2, SInt32 offset, Boolean is_virtual, Boolean is_public) { - BCL *node; - ClassList *base; - Boolean new_is_public; - - for (node = bcl; node; node = node->next) { - if (node->tclass == tclass2) { - if (is_virtual && node->is_virtual) { - if (is_public) - node->is_public = 1; - } else { - CExcept_MakeBaseClassListAmbig(bcl, tclass2); - } - return bcl; - } - } - - node = lalloc(sizeof(BCL)); - node->tclass = tclass2; - node->offset = offset; - node->is_virtual = is_virtual; - node->is_public = is_public; - node->is_ambig = 0; - node->next = bcl; - bcl = node; - - for (base = tclass2->bases; base; base = base->next) { - new_is_public = is_public && (base->access == ACCESSPUBLIC); - bcl = base->is_virtual - ? CExcept_GetBaseClassList(bcl, tclass1, base->base, CClass_VirtualBaseOffset(tclass1, base->base), 1, new_is_public) - : CExcept_GetBaseClassList(bcl, tclass1, base->base, offset + base->offset, 0, new_is_public); - } - - return bcl; -} - -static void CExcept_MangleClass(TypeClass *tclass) { - BCL *bcl; - char buf[20]; - - for (bcl = CExcept_GetBaseClassList(NULL, tclass, tclass, 0, 0, 1); bcl; bcl = bcl->next) { - if (bcl->is_public && !bcl->is_ambig) { - CExcept_MangleClassName(bcl->tclass); - AppendGListByte(&name_mangle_list, '!'); - - if (bcl->offset) { - sprintf(buf, "%" PRId32 "!", bcl->offset); - AppendGListName(&name_mangle_list, buf); - } else { - AppendGListByte(&name_mangle_list, '!'); - } - } - } -} - -static ENode *CExcept_GetTypeID(Type *type, UInt32 qual, Boolean flag) { - ENode *expr; - TypePointer my_tptr; - - if (IS_TYPE_REFERENCE(type)) - type = TPTR_TARGET(type); - - if (IS_TYPE_CLASS(type) || (IS_TYPE_POINTER_ONLY(type) && IS_TYPE_CLASS(TPTR_TARGET(type)))) { - name_mangle_list.size = 0; - if (IS_TYPE_POINTER_ONLY(type)) { - AppendGListByte(&name_mangle_list, '*'); - type = TPTR_TARGET(type); - } else { - AppendGListByte(&name_mangle_list, '!'); - } - - if (flag) { - CExcept_MangleClass(TYPE_CLASS(type)); - } else { - CExcept_MangleClassName(TYPE_CLASS(type)); - AppendGListByte(&name_mangle_list, '!'); - } - } else { - if (IS_TYPE_POINTER_ONLY(type)) { - if (TPTR_QUAL(type) & (Q_CONST | Q_VOLATILE)) { - my_tptr = *TYPE_POINTER(type); - my_tptr.qual = 0; - type = TYPE(&my_tptr); - } - } else { - qual = 0; - } - CMangler_MangleType(type, qual); - } - - AppendGListByte(&name_mangle_list, 0); - - expr = CExpr_NewENode(ESTRINGCONST); - expr->rtype = CDecl_NewPointerType(TYPE(&stchar)); - expr->data.string.size = name_mangle_list.size; - expr->data.string.data = galloc(name_mangle_list.size); - memcpy(expr->data.string.data, *name_mangle_list.data, name_mangle_list.size); - return expr; -} - -static Object *CExcept_TypeID(Type *type, UInt32 qual) { - ENode *expr = CExcept_GetTypeID(type, qual, 0); - CError_ASSERT(1086, expr->type == ESTRINGCONST); - return CInit_DeclareString(expr->data.string.data, expr->data.string.size, 0, 0); -} - -void CExcept_ScanExceptionSpecification(TypeFunc *tfunc) { - ExceptSpecList *exspecs; - ExceptSpecList *exspec; - DeclInfo di; - - exspecs = NULL; - - if (lex() != '(') { - CError_Error(CErrorStr114); - return; - } - - if ((tk = lex()) != ')') { - while (1) { - memclrw(&di, sizeof(di)); - CParser_GetDeclSpecs(&di, 0); - if (di.storageclass) - CError_Error(CErrorStr177); - - CError_QualifierCheck(di.qual & ~(Q_CONST | Q_VOLATILE | Q_PASCAL | Q_ALIGNED_MASK)); - - scandeclarator(&di); - if (di.name) - CError_Error(CErrorStr146); - - if (IS_TYPE_POINTER_ONLY(di.thetype)) { - if (TPTR_QUAL(di.thetype) & (Q_CONST | Q_VOLATILE)) { - TypePointer *newtype = galloc(sizeof(TypePointer)); - *newtype = *TYPE_POINTER(di.thetype); - newtype->qual = 0; - di.thetype = TYPE(newtype); - } - } else { - di.qual = 0; - } - - for (exspec = exspecs; exspec; exspec = exspec->next) { - if (is_typesame(exspec->type, di.thetype) && exspec->qual == di.qual) - break; - } - - if (!exspec) { - exspec = galloc(sizeof(ExceptSpecList)); - memclrw(exspec, sizeof(ExceptSpecList)); - exspec->next = exspecs; - exspec->type = di.thetype; - exspec->qual = di.qual; - exspecs = exspec; - } - - if (tk == ')') - break; - - if (tk != ',') { - CError_Error(CErrorStr115); - break; - } - - tk = lex(); - } - } - - if (!exspecs) { - exspecs = galloc(sizeof(ExceptSpecList)); - memclrw(exspecs, sizeof(ExceptSpecList)); - } - tfunc->exspecs = exspecs; - tk = lex(); -} - -static ENode *CExcept_CallCopyCtor(Object *object, Type *type, ENode *expr1, ENode *expr2) { - ENodeList *list; - ENode *expr; - FuncArg *arg; - - if ( - !IS_TYPE_FUNC(object->type) || - !(arg = TYPE_FUNC(object->type)->args) || - !(arg = arg->next) - ) - CError_FATAL(1169); - - expr = funccallexpr(object, expr1, NULL, NULL, NULL); - list = expr->data.funccall.args; - - if (TYPE_CLASS(type)->flags & CLASS_HAS_VBASES) { - CError_ASSERT(1179, arg = arg->next); - list->next = lalloc(sizeof(ENodeList)); - list = list->next; - list->next = NULL; - list->node = intconstnode(TYPE(&stsignedshort), 1); - } - - list->next = lalloc(sizeof(ENodeList)); - list = list->next; - list->next = NULL; - list->node = expr2; - - while ((arg = arg->next)) { - CError_ASSERT(1195, arg->dexpr); - - list->next = lalloc(sizeof(ENodeList)); - list = list->next; - list->next = NULL; - list->node = CExpr_GetDefaultArgument(expr->data.funccall.funcref, arg); - } - - return expr; -} - -ENode *CExcept_ScanThrowExpression(void) { - ENode *expr; - Object *func; - ENode *resultExpr; - Object *obj; - ENode *thrownExpr; - ENode *tempExpr; - - if (!copts.exceptions) - CError_Error(CErrorStr252); - - switch ((tk = lex())) { - case ')': - case ',': - case ':': - case ';': - expr = funccallexpr(Xthrw_func, nullnode(), nullnode(), nullnode(), NULL); - break; - default: - thrownExpr = pointer_generation(assignment_expression()); - obj = create_temp_object(thrownExpr->rtype); - if (!IS_TYPE_CLASS(thrownExpr->rtype) || !(resultExpr = CExpr_IsTempConstruction(thrownExpr, thrownExpr->rtype, &expr))) { - tempExpr = create_objectrefnode(obj); - if (IS_TYPE_CLASS(thrownExpr->rtype) && (func = CClass_CopyConstructor(TYPE_CLASS(thrownExpr->rtype)))) { - resultExpr = CExcept_CallCopyCtor(func, thrownExpr->rtype, tempExpr, getnodeaddress(thrownExpr, 0)); - } else { - if (thrownExpr->rtype->size == 0) - CError_Error(CErrorStr146); - - tempExpr = makemonadicnode(tempExpr, EINDIRECT); - tempExpr->rtype = thrownExpr->rtype; - resultExpr = makediadicnode(tempExpr, thrownExpr, EASS); - resultExpr = makediadicnode(resultExpr, create_objectrefnode(obj), ECOMMA); - resultExpr->rtype = TYPE(&void_ptr); - } - } else { - *expr = *create_objectrefnode(obj); - } - - expr = CExcept_GetTypeID(thrownExpr->rtype, ENODE_QUALS(thrownExpr), 1); - if (IS_TYPE_CLASS(thrownExpr->rtype) && (func = CClass_Destructor(TYPE_CLASS(thrownExpr->rtype)))) { - expr = funccallexpr( - Xthrw_func, - expr, - resultExpr, - create_objectrefnode(CABI_GetDestructorObject(func, CABIDestroy1)), - NULL); - } else { - expr = funccallexpr( - Xthrw_func, - expr, - resultExpr, - nullnode(), - NULL); - } - } - - expr->flags |= ENODE_FLAG_VOLATILE; - return expr; -} - -static Boolean CExcept_MightNeedDtor(Type *type) { - if (type) { - if (IS_TYPE_CLASS(type)) { - if (!CClass_Destructor(TYPE_CLASS(type))) - return 0; - } else if (IS_TYPE_POINTER_ONLY(type)) { - if (!(TPTR_QUAL(type) & Q_REFERENCE) || !IS_TYPE_CLASS(TPTR_TARGET(type))) - return 0; - } else { - return 0; - } - } - - return 1; -} - -typedef struct CatchBlock { - struct CatchBlock *next; - Object *catch_object; - Object *catch_info_object; - Statement *stmt; - Statement *anotherStmt; - Type *type; - UInt32 qual; -} CatchBlock; - -static void CExcept_PatchDObjStack(Statement *beginCatchStmt, Statement *tryEndStmt, Statement *endStmt, CatchBlock *catchBlock) { - ExceptionAction *ea; - ExceptionAction *stackHead; - ExceptionAction *stackTail; - ExceptionAction *firstEA; - Statement *stmt; - Object *catch_info_object; - Boolean call_dtor; - - catch_info_object = catchBlock->catch_info_object; - call_dtor = 0; - stackHead = stackTail = beginCatchStmt->dobjstack; - firstEA = NULL; - - while (catchBlock) { - ea = lalloc(sizeof(ExceptionAction)); - memclrw(ea, sizeof(ExceptionAction)); - - ea->prev = stackTail; - stackTail = ea; - - if (!firstEA) - firstEA = ea; - - ea->type = EAT_CATCHBLOCK; - ea->data.catch_block.catch_object = catchBlock->catch_object; - ea->data.catch_block.catch_label = catchBlock->stmt->label; - if (catchBlock->type) - ea->data.catch_block.catch_typeid = CExcept_TypeID(catchBlock->type, catchBlock->qual); - ea->data.catch_block.catch_info_object = catch_info_object; - - if (!call_dtor && CExcept_MightNeedDtor(catchBlock->type)) - call_dtor = 1; - - ea->data.catch_block.catch_type = catchBlock->type; - ea->data.catch_block.catch_qual = catchBlock->qual; - catchBlock = catchBlock->next; - } - - stmt = beginCatchStmt; - while (1) { - if ((ea = stmt->dobjstack) != stackHead) { - while (1) { - CError_ASSERT(1404, ea); - if (ea->prev == stackTail) - break; - if (ea->prev == stackHead) { - ea->prev = stackTail; - break; - } - ea = ea->prev; - } - } else { - stmt->dobjstack = stackTail; - } - - if (stmt == endStmt) - break; - - if (stmt == tryEndStmt) { - ea = lalloc(sizeof(ExceptionAction)); - memclrw(ea, sizeof(ExceptionAction)); - ea->prev = stackHead; - ea->type = EAT_ACTIVECATCHBLOCK; - ea->data.active_catch_block.catch_info_object = catch_info_object; - ea->data.active_catch_block.call_dtor = call_dtor; - stackTail = ea; - } - - stmt = stmt->next; - CError_ASSERT(1426, stmt); - } - - cexcept_hasdobjects = 1; -} - -static void CExcept_CheckTryObjects(ENode *expr) { - if (expr->data.objref->datatype == DLOCAL && expr->data.objref->u.var.info) - expr->data.objref->u.var.info->noregister = 1; -} - -static ENode *CExcept_CatchExpressionInit(DeclInfo *di, CatchBlock *catchBlock) { - Object *catch_object; - Object *copyCtor; - Object *dtor; - ENode *expr; - - if (CScope_FindName(cscope_current, di->name)) - CError_Error(CErrorStr122, di->name->name); - - catch_object = CParser_NewLocalDataObject(di, 1); - CFunc_SetupLocalVarInfo(catch_object); - CScope_AddObject(cscope_current, di->name, OBJ_BASE(catch_object)); - catchBlock->catch_object = catch_object; - - expr = makediadicnode( - create_objectrefnode(catchBlock->catch_info_object), - intconstnode(TYPE(&stunsignedlong), 12), - EADD); - expr->rtype = CDecl_NewPointerType(CDecl_NewPointerType(di->thetype)); - - expr = makemonadicnode(expr, EINDIRECT); - expr->rtype = CDecl_NewPointerType(di->thetype); - - if (IS_TYPE_REFERENCE(di->thetype)) - return makediadicnode(create_objectnode2(catch_object), expr, EASS); - - if (IS_TYPE_CLASS(di->thetype) && (copyCtor = CClass_CopyConstructor(TYPE_CLASS(di->thetype)))) { - dtor = CClass_Destructor(TYPE_CLASS(di->thetype)); - return CExcept_CallCopyCtor( - copyCtor, - di->thetype, - (dtor == NULL) ? create_objectrefnode(catch_object) : CExcept_RegisterDestructorObject(catch_object, 0, dtor, 0), - expr); - } - - expr = makemonadicnode(expr, EINDIRECT); - expr->rtype = di->thetype; - return makediadicnode(create_objectnode(catch_object), expr, EASS); -} - -void CExcept_ScanTryBlock(DeclThing *dt, Boolean flag) { - Object *catch_info_object; // r27 - Statement *beginCatchStmt; // r14 - Statement *tryEndStmt; // r16 - Statement *endStmt; // r17 - Statement *stmt; // r14 - CLabel *catchEndLabel; // r19 - CLabel *endLabel; // r24 - CatchBlock *catchStack; // r23 - CatchBlock *catchBlock; // r22 - DeclBlock *declBlock; // r20 - DeclInfo di; - - if (!copts.exceptions) - CError_Error(CErrorStr252); - - catch_info_object = create_temp_object(TYPE(&catchinfostruct)); - if (cexcept_magic) { - catch_info_object->name = GetHashNameNodeExport("__exception_magic"); - CScope_AddObject(cscope_current, catch_info_object->name, OBJ_BASE(catch_info_object)); - } - - stmt = CFunc_AppendStatement(ST_LABEL); - stmt->flags = StmtFlag_1; - stmt->label = newlabel(); - stmt->label->stmt = stmt; - - beginCatchStmt = CFunc_AppendStatement(ST_BEGINCATCH); - beginCatchStmt->expr = create_objectrefnode(catch_info_object); - - if (tk != '{') { - CError_Error(CErrorStr135); - return; - } - - CFunc_CompoundStatement(dt); - - if (tk != TK_CATCH) { - CError_Error(CErrorStr242); - return; - } - - stmt = CFunc_AppendStatement(ST_GOTO); - catchEndLabel = stmt->label = newlabel(); - tryEndStmt = stmt; - - endLabel = newlabel(); - catchStack = NULL; - - while (1) { - CPrep_GetFileOffsetInfo2(&cparser_fileoffset, &sourceoffset, &sourcefilepath); - - stmt = CFunc_AppendStatement(ST_LABEL); - stmt->flags = StmtFlag_1; - stmt->label = newlabel(); - stmt->label->stmt = stmt; - - declBlock = NULL; - - catchBlock = lalloc(sizeof(ExceptionAction)); - memclrw(catchBlock, sizeof(ExceptionAction)); - catchBlock->next = catchStack; - catchStack = catchBlock; - - catchBlock->stmt = stmt; - catchBlock->catch_info_object = catch_info_object; - - if ((tk = lex()) != '(') { - CError_Error(CErrorStr114); - break; - } - - if ((tk = lex()) == TK_ELLIPSIS) { - tk = lex(); - } else { - memclrw(&di, sizeof(di)); - CParser_GetDeclSpecs(&di, 0); - - if (di.x48) - CError_Error(CErrorStr121); - if (di.storageclass) - CError_Error(CErrorStr177); - - CError_QualifierCheck(di.qual & ~(Q_CONST | Q_VOLATILE | Q_PASCAL | Q_ALIGNED_MASK)); - - scandeclarator(&di); - - if (IS_TYPE_FUNC(di.thetype)) - di.thetype = CDecl_NewPointerType(di.thetype); - else if (IS_TYPE_ARRAY(di.thetype)) - di.thetype = CDecl_NewPointerType(TPTR_TARGET(di.thetype)); - - IsCompleteType(di.thetype); - if (IS_TYPE_CLASS(di.thetype) && (TYPE_CLASS(di.thetype)->flags & CLASS_ABSTRACT)) - CError_AbstractClassError(TYPE_CLASS(di.thetype)); - - catchBlock->type = di.thetype; - catchBlock->qual = di.qual; - - if (di.name) { - ENode *expr; - declBlock = CFunc_NewDeclBlock(); - expr = CExcept_CatchExpressionInit(&di, catchBlock); - stmt = CFunc_AppendStatement(ST_EXPRESSION); - stmt->expr = expr; - } - } - - if (tk != ')') { - CError_Error(CErrorStr115); - break; - } - - if ((tk = lex()) != '{') { - CError_Error(CErrorStr123); - break; - } - - CFunc_CompoundStatement(dt); - if (flag) { - stmt = CFunc_AppendStatement(ST_EXPRESSION); - stmt->expr = funccallexpr(Xthrw_func, nullnode(), nullnode(), nullnode(), NULL); - } - - catchBlock->anotherStmt = stmt; - - if (declBlock) - CFunc_RestoreBlock(declBlock); - - if (tk != TK_CATCH) - break; - - CFunc_AppendStatement(ST_GOTO)->label = endLabel; - } - - endStmt = CFunc_AppendStatement(ST_LABEL); - endStmt->label = endLabel; - endLabel->stmt = endStmt; - - CExcept_PatchDObjStack(beginCatchStmt, tryEndStmt, endStmt, catchBlock); - - stmt = CFunc_AppendStatement(ST_LABEL); - stmt->label = catchEndLabel; - catchEndLabel->stmt = stmt; -} - -static Statement *CExcept_InsertPrevStatement(StatementType sttype) { - Statement *stmt = CFunc_InsertStatement(sttype, cexcept_prevstmt); - stmt->sourceoffset = stmt->next->sourceoffset; - stmt->sourcefilepath = stmt->next->sourcefilepath; - stmt->dobjstack = cexcept_eabefore; - return stmt; -} - -static Object *CExcept_GetETEMPObject(ENode *expr) { - UniqueObj *uobj; - SInt32 id; - - if ((id = expr->data.temp.uniqueid)) { - for (uobj = cexcept_uniqueobjs; uobj; uobj = uobj->next) { - if (uobj->uniqueid == id) - return uobj->object; - } - - uobj = galloc(sizeof(UniqueObj)); - uobj->next = cexcept_uniqueobjs; - cexcept_uniqueobjs = uobj; - uobj->uniqueid = id; - return (uobj->object = create_temp_object(expr->data.temp.type)); - } else { - return create_temp_object(expr->data.temp.type); - } -} - -static ENode *CExcept_TempTrans_ETEMP(ENode *expr) { - Object *object; - ExceptionAction *ea; - DtorTemp *dtorTemp; - Object *dtor; - - object = CExcept_GetETEMPObject(expr); - if (expr->data.temp.needs_dtor) { - dtorTemp = lalloc(sizeof(DtorTemp)); - dtorTemp->next = cexcept_dtortemps; - cexcept_dtortemps = dtorTemp; - dtorTemp->object = object; - dtorTemp->temp = NULL; - - if ( - !IS_TYPE_CLASS(expr->data.temp.type) || - !(dtorTemp->dtor = CClass_Destructor(TYPE_CLASS(expr->data.temp.type))) - ) - CError_FATAL(1749); - - ea = lalloc(sizeof(ExceptionAction)); - ea->prev = cexcept_eabefore; - cexcept_eabefore = ea; - ea->type = EAT_DESTROYLOCAL; - ea->data.destroy_local.local = dtorTemp->object; - ea->data.destroy_local.dtor = CABI_GetDestructorObject(dtorTemp->dtor, CABIDestroy1); - - ea = lalloc(sizeof(ExceptionAction)); - *ea = *cexcept_eabefore; - ea->prev = cexcept_eaafter; - cexcept_eaafter = ea; - } - - expr->type = EOBJREF; - expr->data.objref = object; - return expr; -} - -static ENode *CExcept_TransNewException(ENode *expr, Boolean isCond) { - Object *tempObj; - CLabel *label; - Boolean isArray; - Statement *stmt; - ExceptionAction *ea; - ENode *result; - - isArray = expr->type == ENEWEXCEPTIONARRAY; - - if (isCond) { - expr->data.newexception.initexpr = CExcept_TempTransExprCond(expr->data.newexception.initexpr); - expr->data.newexception.tryexpr = CExcept_TempTransExprCond(expr->data.newexception.tryexpr); - tempObj = create_temp_object(TYPE(&stchar)); - - stmt = CExcept_InsertPrevStatement(ST_EXPRESSION); - stmt->expr = makediadicnode(create_objectnode(tempObj), intconstnode(TYPE(&stchar), 0), EASS); - cexcept_prevstmt = stmt; - - ea = lalloc(sizeof(ExceptionAction)); - ea->prev = cexcept_eabefore; - cexcept_eabefore = ea; - - ea->type = EAT_DELETEPOINTERCOND; - ea->data.delete_pointer_cond.pointerobject = expr->data.newexception.pointertemp; - ea->data.delete_pointer_cond.deletefunc = expr->data.newexception.deletefunc; - ea->data.delete_pointer_cond.cond = tempObj; - - if (isArray) { - result = makediadicnode( - makediadicnode( - expr->data.newexception.initexpr, - makediadicnode(create_objectnode(tempObj), intconstnode(TYPE(&stchar), 1), EASS), - ECOMMA - ), - expr->data.newexception.tryexpr, - ECOMMA - ); - - result = makediadicnode( - result, - makediadicnode(create_objectnode(tempObj), intconstnode(TYPE(&stchar), 0), EASS), - ECOMMA - ); - - result = makediadicnode( - result, - create_objectnode(expr->data.newexception.pointertemp), - ECOMMA - ); - } else { - result = makediadicnode( - makediadicnode(create_objectnode(tempObj), intconstnode(TYPE(&stchar), 1), EASS), - expr->data.newexception.tryexpr, - ECOMMA - ); - - result = makediadicnode( - expr->data.newexception.initexpr, - makediadicnode( - result, - makediadicnode(create_objectnode(tempObj), intconstnode(TYPE(&stchar), 0), EASS), - ECOMMA - ), - ELAND - ); - - result = makediadicnode( - result, - create_objectnode(expr->data.newexception.pointertemp), - ECOMMA - ); - } - } else { - expr->data.newexception.initexpr = CExcept_TempTransExpr(expr->data.newexception.initexpr); - expr->data.newexception.tryexpr = CExcept_TempTransExpr(expr->data.newexception.tryexpr); - - if (isArray) { - stmt = CExcept_InsertPrevStatement(ST_EXPRESSION); - stmt->expr = expr->data.newexception.initexpr; - } else { - stmt = CExcept_InsertPrevStatement(ST_IFNGOTO); - stmt->expr = expr->data.newexception.initexpr; - label = newlabel(); - stmt->label = label; - } - - stmt = CFunc_InsertStatement(ST_EXPRESSION, stmt); - stmt->expr = expr->data.newexception.tryexpr; - - ea = lalloc(sizeof(ExceptionAction)); - ea->prev = cexcept_eabefore; - ea->type = EAT_DELETEPOINTER; - ea->data.delete_pointer.pointerobject = expr->data.newexception.pointertemp; - ea->data.delete_pointer.deletefunc = expr->data.newexception.deletefunc; - stmt->dobjstack = ea; - - if (!isArray) { - stmt = CFunc_InsertStatement(ST_LABEL, stmt); - stmt->label = label; - label->stmt = stmt; - stmt->dobjstack = cexcept_eabefore; - } - - cexcept_prevstmt = stmt; - result = create_objectnode(expr->data.newexception.pointertemp); - } - - result->rtype = expr->rtype; - return result; -} - -static ENode *CExcept_TransInitTryCatch(ENode *expr, Boolean isCond) { - CLabel *label1; - CLabel *label2; - CLabel *label3; - Object *catch_info_object; - Statement *stmt; - ExceptionAction *ea; - - cexcept_hastrycatch = 1; - - if (isCond) { - CError_ASSERT(1877, !cexcept_expandtrycatch); - - cexcept_serialize = 1; - expr->data.itc.initexpr = CExcept_TempTransExprCond(expr->data.itc.initexpr); - expr->data.itc.tryexpr = CExcept_TempTransExprCond(expr->data.itc.tryexpr); - expr->data.itc.catchexpr = CExcept_TempTransExprCond(expr->data.itc.catchexpr); - expr->data.itc.result = CExcept_TempTransExprCond(expr->data.itc.result); - return expr; - } - - expr->data.itc.initexpr = CExcept_TempTransExpr(expr->data.itc.initexpr); - expr->data.itc.tryexpr = CExcept_TempTransExpr(expr->data.itc.tryexpr); - expr->data.itc.catchexpr = CExcept_TempTransExpr(expr->data.itc.catchexpr); - expr->data.itc.result = CExcept_TempTransExpr(expr->data.itc.result); - - if (!cexcept_expandtrycatch) - return expr; - - label1 = newlabel(); - label2 = newlabel(); - label3 = newlabel(); - - catch_info_object = create_temp_object(TYPE(&catchinfostruct)); - - stmt = CExcept_InsertPrevStatement(ST_IFNGOTO); - stmt->expr = expr->data.itc.initexpr; - stmt->label = label3; - - ea = lalloc(sizeof(ExceptionAction)); - memclrw(ea, sizeof(ExceptionAction)); - ea->type = EAT_CATCHBLOCK; - ea->data.catch_block.catch_label = label2; - ea->data.catch_block.catch_info_object = catch_info_object; - ea->prev = stmt->dobjstack; - - stmt = CFunc_InsertStatement(ST_LABEL, stmt); - stmt->flags = StmtFlag_1; - stmt->label = label1; - label1->stmt = stmt; - stmt->dobjstack = ea; - - stmt = CFunc_InsertStatement(ST_BEGINCATCH, stmt); - stmt->expr = create_objectrefnode(catch_info_object); - - stmt = CFunc_InsertStatement(ST_EXPRESSION, stmt); - stmt->expr = expr->data.itc.tryexpr; - - stmt = CFunc_InsertStatement(ST_GOTO, stmt); - stmt->label = label3; - - CError_ASSERT(1928, stmt->dobjstack == ea); - - stmt->dobjstack = ea->prev; - - ea = lalloc(sizeof(ExceptionAction)); - memclrw(ea, sizeof(ExceptionAction)); - ea->type = EAT_ACTIVECATCHBLOCK; - ea->data.active_catch_block.catch_info_object = catch_info_object; - ea->prev = stmt->dobjstack; - - stmt = CFunc_InsertStatement(ST_LABEL, stmt); - stmt->flags = StmtFlag_1; - stmt->label = label2; - label2->stmt = stmt; - stmt->dobjstack = ea; - - stmt = CFunc_InsertStatement(ST_EXPRESSION, stmt); - stmt->expr = expr->data.itc.catchexpr; - - stmt = CFunc_InsertStatement(ST_EXPRESSION, stmt); - stmt->expr = funccallexpr(Xthrw_func, nullnode(), nullnode(), nullnode(), NULL); - - stmt = CFunc_InsertStatement(ST_LABEL, stmt); - stmt->label = label3; - label3->stmt = stmt; - - CError_ASSERT(1968, stmt->dobjstack == ea); - - stmt->dobjstack = ea->prev; - - cexcept_prevstmt = stmt; - return expr->data.itc.result; -} - -static ENode *CExcept_TempTransFuncCall(ENode *expr, Boolean isCond) { - ENodeList *tempArg; - ENodeList **argArray; - ENodeList *args; - ExceptionAction *ea; - Statement *stmt; - DtorTemp *dtorTemp; - ENode *tempNode; - - tempArg = NULL; - if ((args = expr->data.funccall.args)) { - tempNode = args->node; - if (tempNode->type == ETEMP) { - if (tempNode->data.temp.needs_dtor) - tempArg = args; - } else if (args->next) { - tempNode = args->next->node; - if (tempNode->type == ETEMP) { - if (tempNode->data.temp.needs_dtor) - tempArg = args->next; - } - } - } - - if (tempArg) { - if (isCond) { - ENodeList *arg = args; - SInt32 i = 0; - while (arg) { - arg = arg->next; - i++; - } - - argArray = lalloc(sizeof(ENodeList *) * i); - for (args = expr->data.funccall.args, i = 0; args; args = args->next) - argArray[i++] = args; - - while (i > 0) { - i--; - if (argArray[i] != tempArg) - argArray[i]->node = CExcept_TempTransExprCond(argArray[i]->node); - } - } else { - while (args) { - if (args != tempArg) - args->node = CExcept_TempTransExpr(args->node); - args = args->next; - } - } - - dtorTemp = lalloc(sizeof(DtorTemp)); - dtorTemp->next = cexcept_dtortemps; - cexcept_dtortemps = dtorTemp; - - dtorTemp->object = CExcept_GetETEMPObject(tempNode); - dtorTemp->temp = NULL; - - if ( - !IS_TYPE_CLASS(tempNode->data.temp.type) || - !(dtorTemp->dtor = CClass_Destructor(TYPE_CLASS(tempNode->data.temp.type))) - ) - CError_FATAL(2046); - - tempNode->type = EOBJREF; - tempNode->data.objref = dtorTemp->object; - - if (isCond) { - Type *type24 = expr->rtype; - dtorTemp->temp = create_temp_object(TYPE(&stchar)); - - expr = makediadicnode( - expr, - makediadicnode(create_objectnode(dtorTemp->temp), intconstnode(TYPE(&stchar), 1), EASS), - ECOMMA - ); - - expr = makediadicnode( - expr, - create_objectrefnode(dtorTemp->object), - ECOMMA - ); - expr->rtype = type24; - - stmt = CExcept_InsertPrevStatement(ST_EXPRESSION); - stmt->expr = makediadicnode( - create_objectnode(dtorTemp->temp), - intconstnode(TYPE(&stchar), 0), - EASS - ); - cexcept_prevstmt = stmt; - - ea = lalloc(sizeof(ExceptionAction)); - ea->prev = cexcept_eabefore; - cexcept_eabefore = ea; - - ea->type = EAT_DESTROYLOCALCOND; - ea->data.destroy_local_cond.local = dtorTemp->object; - ea->data.destroy_local_cond.dtor = CABI_GetDestructorObject(dtorTemp->dtor, CABIDestroy1); - ea->data.destroy_local_cond.cond = dtorTemp->temp; - - ea = lalloc(sizeof(ExceptionAction)); - *ea = *cexcept_eabefore; - ea->prev = cexcept_eaafter; - cexcept_eaafter = ea; - } else { - stmt = CExcept_InsertPrevStatement(ST_EXPRESSION); - stmt->expr = expr; - cexcept_prevstmt = stmt; - - ea = lalloc(sizeof(ExceptionAction)); - ea->prev = cexcept_eabefore; - cexcept_eabefore = ea; - - ea->type = EAT_DESTROYLOCAL; - ea->data.destroy_local.local = dtorTemp->object; - ea->data.destroy_local.dtor = CABI_GetDestructorObject(dtorTemp->dtor, CABIDestroy1); - - ea = lalloc(sizeof(ExceptionAction)); - *ea = *cexcept_eabefore; - ea->prev = cexcept_eaafter; - cexcept_eaafter = ea; - - expr = lalloc(sizeof(ENode)); - *expr = *stmt->expr; - expr->type = EOBJREF; - expr->data.objref = tempArg->node->data.objref; - } - return expr; - } else { - if (isCond) { - SInt32 i = 0; - while (args) { - args = args->next; - i++; - } - - argArray = lalloc(sizeof(ENodeList *) * i); - for (args = expr->data.funccall.args, i = 0; args; args = args->next) - argArray[i++] = args; - - while (i > 0) { - i--; - argArray[i]->node = CExcept_TempTransExprCond(argArray[i]->node); - } - - expr->data.funccall.funcref = CExcept_TempTransExprCond(expr->data.funccall.funcref); - } else { - while (args) { - args->node = CExcept_TempTransExpr(args->node); - args = args->next; - } - - expr->data.funccall.funcref = CExcept_TempTransExpr(expr->data.funccall.funcref); - } - - return expr; - } -} - -static ENode *CExcept_TempTransExprCond(ENode *expr) { - switch (expr->type) { - case ETEMP: - return CExcept_TempTrans_ETEMP(expr); - case ENEWEXCEPTION: - case ENEWEXCEPTIONARRAY: - return CExcept_TransNewException(expr, 1); - case EINITTRYCATCH: - return CExcept_TransInitTryCatch(expr, 1); - case ENULLCHECK: - expr->data.nullcheck.nullcheckexpr = CExcept_TempTransExprCond(expr->data.nullcheck.nullcheckexpr); - expr->data.nullcheck.condexpr = CExcept_TempTransExprCond(expr->data.nullcheck.condexpr); - return expr; - case ECOND: - expr->data.cond.cond = CExcept_TempTransExprCond(expr->data.cond.cond); - expr->data.cond.expr1 = CExcept_TempTransExprCond(expr->data.cond.expr1); - expr->data.cond.expr2 = CExcept_TempTransExprCond(expr->data.cond.expr2); - return expr; - case ELAND: - case ELOR: - expr->data.diadic.left = CExcept_TempTransExprCond(expr->data.diadic.left); - expr->data.diadic.right = CExcept_TempTransExprCond(expr->data.diadic.right); - return expr; - case EFUNCCALL: - case EFUNCCALLP: - return CExcept_TempTransFuncCall(expr, 1); - case EMUL: - case EDIV: - case EMODULO: - case EADD: - case ESUB: - case ESHL: - case ESHR: - case ELESS: - case EGREATER: - case ELESSEQU: - case EGREATEREQU: - case EEQU: - case ENOTEQU: - case EAND: - case EXOR: - case EOR: - case EASS: - case EMULASS: - case EDIVASS: - case EMODASS: - case EADDASS: - case ESUBASS: - case ESHLASS: - case ESHRASS: - case EANDASS: - case EXORASS: - case EORASS: - case ECOMMA: - case EROTL: - case EROTR: - expr->data.diadic.left = CExcept_TempTransExprCond(expr->data.diadic.left); - expr->data.diadic.right = CExcept_TempTransExprCond(expr->data.diadic.right); - return expr; - case EPOSTINC: - case EPOSTDEC: - case EPREINC: - case EPREDEC: - case EINDIRECT: - case EMONMIN: - case EBINNOT: - case ELOGNOT: - case ETYPCON: - case EBITFIELD: - expr->data.monadic = CExcept_TempTransExprCond(expr->data.monadic); - return expr; - case EINTCONST: - case EFLOATCONST: - case ESTRINGCONST: - case EOBJREF: - case EPRECOMP: - case ELABEL: - case EINSTRUCTION: - case EVECTOR128CONST: - return expr; - default: - CError_FATAL(2236); - return expr; - } -} - -static ENode *CExcept_TempTransExpr(ENode *expr) { - switch (expr->type) { - case ETEMP: - return CExcept_TempTrans_ETEMP(expr); - case ENEWEXCEPTION: - case ENEWEXCEPTIONARRAY: - return CExcept_TransNewException(expr, 0); - case EINITTRYCATCH: - return CExcept_TransInitTryCatch(expr, 0); - case ENULLCHECK: - expr->data.nullcheck.nullcheckexpr = CExcept_TempTransExpr(expr->data.nullcheck.nullcheckexpr); - expr->data.nullcheck.condexpr = CExcept_TempTransExprCond(expr->data.nullcheck.condexpr); - return expr; - case ECOND: - expr->data.cond.cond = CExcept_TempTransExpr(expr->data.cond.cond); - expr->data.cond.expr1 = CExcept_TempTransExprCond(expr->data.cond.expr1); - expr->data.cond.expr2 = CExcept_TempTransExprCond(expr->data.cond.expr2); - return expr; - case ELAND: - case ELOR: - case ECOMMA: - expr->data.diadic.left = CExcept_TempTransExpr(expr->data.diadic.left); - expr->data.diadic.right = CExcept_TempTransExprCond(expr->data.diadic.right); - return expr; - case EFUNCCALL: - case EFUNCCALLP: - return CExcept_TempTransFuncCall(expr, 0); - case EMUL: - case EDIV: - case EMODULO: - case EADD: - case ESUB: - case ESHL: - case ESHR: - case ELESS: - case EGREATER: - case ELESSEQU: - case EGREATEREQU: - case EEQU: - case ENOTEQU: - case EAND: - case EXOR: - case EOR: - case EASS: - case EMULASS: - case EDIVASS: - case EMODASS: - case EADDASS: - case ESUBASS: - case ESHLASS: - case ESHRASS: - case EANDASS: - case EXORASS: - case EORASS: - case EROTL: - case EROTR: - expr->data.diadic.left = CExcept_TempTransExpr(expr->data.diadic.left); - expr->data.diadic.right = CExcept_TempTransExpr(expr->data.diadic.right); - return expr; - case EPOSTINC: - case EPOSTDEC: - case EPREINC: - case EPREDEC: - case EINDIRECT: - case EMONMIN: - case EBINNOT: - case ELOGNOT: - case ETYPCON: - case EBITFIELD: - expr->data.monadic = CExcept_TempTransExpr(expr->data.monadic); - return expr; - case EINTCONST: - case EFLOATCONST: - case ESTRINGCONST: - case EOBJREF: - case EMFPOINTER: - case EPRECOMP: - case ELABEL: - case EOBJLIST: - case EMEMBER: - case EINSTRUCTION: - case EVECTOR128CONST: - return expr; - default: - CError_FATAL(2350); - return expr; - } -} - -static Statement *CExcept_DtorTransform(Statement *stmt) { - DtorTemp *dtorTemp; - Statement *curStmt; - CLabel *lastLabel; - - dtorTemp = cexcept_dtortemps; - curStmt = stmt; - while (dtorTemp) { - if ( - cexcept_eaafter && - (cexcept_eaafter->type == EAT_DESTROYLOCAL || cexcept_eaafter->type == EAT_DESTROYLOCALCOND) && - cexcept_eaafter->data.destroy_local.local == dtorTemp->object - ) - { - cexcept_eaafter = cexcept_eaafter->prev; - } else { - CError_FATAL(2374); - } - - if (dtorTemp->temp) { - curStmt = CFunc_InsertStatement(ST_IFNGOTO, curStmt); - curStmt->expr = create_objectnode(dtorTemp->temp); - curStmt->dobjstack = cexcept_eaafter; - lastLabel = curStmt->label = newlabel(); - } - - curStmt = CFunc_InsertStatement(ST_EXPRESSION, curStmt); - curStmt->expr = CABI_DestroyObject(dtorTemp->dtor, create_objectrefnode(dtorTemp->object), CABIDestroy1, 1, 0); - curStmt->dobjstack = cexcept_eaafter; - - if (dtorTemp->temp) { - curStmt = CFunc_InsertStatement(ST_LABEL, curStmt); - curStmt->label = lastLabel; - lastLabel->stmt = curStmt; - } - - dtorTemp = dtorTemp->next; - } - - return curStmt; -} - -static void CExcept_TempTransform(Statement *stmt, Boolean flag1, Boolean flag2) { - Statement *prevStmt; - Statement *iter; - Statement copy; - Object *tempObj; - - prevStmt = cexcept_prevstmt; - cexcept_dtortemps = NULL; - cexcept_serialize = 0; - cexcept_expandtrycatch = 0; - cexcept_hastrycatch = 0; - stmt->expr = CExcept_TempTransExpr(stmt->expr); - - if (cexcept_hastrycatch) { - cexcept_expandtrycatch = 1; - if (cexcept_serialize) { - CInline_SerializeStatement(stmt); - cexcept_prevstmt = stmt; - } else { - cexcept_prevstmt = prevStmt; - } - - iter = prevStmt; - while (1) { - CError_ASSERT(2425, iter); - - switch (iter->type) { - case ST_RETURN: - CError_ASSERT(2429, iter->expr != NULL); - case ST_EXPRESSION: - case ST_SWITCH: - case ST_IFGOTO: - case ST_IFNGOTO: - iter->expr = CExcept_TempTransExpr(iter->expr); - } - - if (iter == stmt) - break; - cexcept_prevstmt = iter; - iter = iter->next; - } - } - - if (cexcept_dtortemps) { - if (!flag1) { - if (flag2) { - ENode *expr = stmt->expr; - CError_ASSERT(2456, !IS_TYPE_CLASS(expr->rtype) || !CClass_Destructor(TYPE_CLASS(expr->rtype))); - - tempObj = create_temp_object(expr->rtype); - stmt->expr = makediadicnode(create_objectnode(tempObj), expr, EASS); - } - - copy = *stmt; - stmt->type = ST_EXPRESSION; - stmt = CExcept_DtorTransform(stmt); - stmt = CFunc_InsertStatement(copy.type, stmt); - stmt->label = copy.label; - - if (flag2) - stmt->expr = create_objectnode(tempObj); - else - stmt->expr = nullnode(); - } else { - CExcept_DtorTransform(stmt); - } - } -} - -static void CExcept_CleanupExceptionActions(Statement *stmt) { - Statement *iter; - ENode *expr; - ExceptionAction *ea; - - cexcept_prevstmt = stmt; - for (iter = stmt; iter; iter = iter->next) { - cexcept_eabefore = cexcept_eaafter = ea = iter->dobjstack; - - if (iter->flags & StmtFlag_2) { - cexcept_eabefore = ea->prev; - } else if (iter->type == ST_EXPRESSION) { - expr = iter->expr; - while (ENODE_IS(expr, ECOMMA)) - expr = expr->data.diadic.left; - if (ENODE_IS(expr, EINDIRECT)) - expr = expr->data.monadic; - - if ( - ENODE_IS(expr, EFUNCCALL) && - ENODE_IS(expr->data.funccall.funcref, EOBJREF) && - CClass_IsConstructor(expr->data.funccall.funcref->data.objref) && - iter->dobjstack && - iter->dobjstack->type == EAT_DESTROYLOCAL && - expr->data.funccall.args && - ENODE_IS(expr->data.funccall.args->node, EOBJREF) && - expr->data.funccall.args->node->data.objref == iter->dobjstack->data.destroy_local.local - ) - cexcept_eabefore = cexcept_eabefore->prev; - } - - switch (iter->type) { - case ST_EXPRESSION: - CExcept_TempTransform(iter, 1, 0); - break; - case ST_SWITCH: - case ST_IFGOTO: - case ST_IFNGOTO: - CExcept_TempTransform(iter, 0, 1); - break; - case ST_RETURN: - if (iter->expr) { - CExcept_TempTransform( - iter, - 0, - CMach_GetFunctionResultClass(TYPE_FUNC(cscope_currentfunc->type)) != 1 - ); - } - break; - } - - iter->dobjstack = cexcept_eabefore; - cexcept_prevstmt = iter; - } -} - -static void CExcept_InsertSpecificationActions(Statement *stmt, ExceptSpecList *exspecs) { - Statement *iter; - Statement *last; - ExceptionAction *ea_spec; - ExceptionAction *ea; - ExceptSpecList *spec_iter; - SInt32 i; - Object *catch_info_object; - CLabel *label; - - ea_spec = lalloc(sizeof(ExceptionAction)); - memclrw(ea_spec, sizeof(ExceptionAction)); - ea_spec->type = EAT_SPECIFICATION; - - for (iter = stmt; iter; iter = iter->next) { - if ((ea = iter->dobjstack)) { - while (1) { - if (ea->type == EAT_SPECIFICATION) - break; - if (ea->prev == NULL) { - ea->prev = ea_spec; - break; - } - ea = ea->prev; - } - } else { - iter->dobjstack = ea_spec; - } - } - - last = stmt; - while (last->next) - last = last->next; - - if (last->type != ST_GOTO && last->type != ST_RETURN) { - last = CFunc_InsertStatement(ST_RETURN, last); - last->expr = NULL; - last->dobjstack = NULL; - if (TYPE_FUNC(cscope_currentfunc->type)->functype != &stvoid && (copts.pedantic || copts.cplusplus)) - CError_Warning(CErrorStr184); - } - - last = CFunc_InsertStatement(ST_LABEL, last); - last->label = newlabel(); - last->label->stmt = last; - last->flags = StmtFlag_1; - last->dobjstack = NULL; - - catch_info_object = create_temp_object(TYPE(&catchinfostruct)); - - if (!exspecs->type) - exspecs = NULL; - - i = 0; - spec_iter = exspecs; - while (spec_iter) { - spec_iter = spec_iter->next; - i++; - } - - ea_spec->data.specification.unexp_ids = i; - ea_spec->data.specification.unexp_id = galloc(sizeof(Object *) * i); - ea_spec->data.specification.unexp_label = last->label; - ea_spec->data.specification.unexp_info_object = catch_info_object; - - i = 0; - while (exspecs) { - ea_spec->data.specification.unexp_id[i] = CExcept_TypeID(exspecs->type, exspecs->qual); - exspecs = exspecs->next; - i++; - } - - last = CFunc_InsertStatement(ST_EXPRESSION, last); - last->expr = funccallexpr(Xunex_func, create_objectrefnode(catch_info_object), NULL, NULL, NULL); - - ea = lalloc(sizeof(ExceptionAction)); - memclrw(ea, sizeof(ExceptionAction)); - ea->type = EAT_ACTIVECATCHBLOCK; - ea->data.active_catch_block.catch_info_object = catch_info_object; - ea->data.active_catch_block.call_dtor = 1; - last->dobjstack = ea; - - last = CFunc_InsertStatement(ST_LABEL, last); - last->label = label = newlabel(); - last->label->stmt = last; - last->dobjstack = NULL; - - last = CFunc_InsertStatement(ST_GOTO, last); - last->label = label; -} - -static void CExcept_HasFuncCallCallBack(ENode *expr) { - ENode *funcref = expr->data.funccall.funcref; - if (ENODE_IS(funcref, EOBJREF)) { - Object *func = funcref->data.objref; - if (CExcept_CanThrowException(func, func->datatype == DVFUNC && !(expr->flags & ENODE_FLAG_80))) - cexcept_canthrow = 1; - } else { - cexcept_canthrow = 1; - } -} - -static Boolean CExcept_CanThrowCheck(Object *func, Statement *stmt) { - cexcept_canthrow = 0; - - while (stmt) { - switch (stmt->type) { - case ST_NOP: - case ST_LABEL: - case ST_GOTO: - case ST_ASM: - break; - case ST_RETURN: - if (!stmt->expr) - break; - case ST_EXPRESSION: - case ST_SWITCH: - case ST_IFGOTO: - case ST_IFNGOTO: - case ST_BEGINCATCH: - case ST_ENDCATCH: - case ST_ENDCATCHDTOR: - case ST_GOTOEXPR: - CExpr_SearchExprTree(stmt->expr, CExcept_HasFuncCallCallBack, 2, EFUNCCALL, EFUNCCALLP); - break; - default: - CError_FATAL(2687); - } - stmt = stmt->next; - } - - if (!cexcept_canthrow) { - TYPE_FUNC(cscope_currentfunc->type)->flags |= FUNC_NOTHROW; - return 0; - } else { - return 1; - } -} - -void CExcept_ExceptionTansform(Statement *stmt) { - cexcept_uniqueobjs = NULL; - CExcept_CleanupExceptionActions(stmt); - - if (cscope_currentfunc && CExcept_CanThrowCheck(cscope_currentfunc, stmt)) { - CError_ASSERT(2716, IS_TYPE_FUNC(cscope_currentfunc->type)); - if (TYPE_FUNC(cscope_currentfunc->type)->exspecs && copts.exceptions) - CExcept_InsertSpecificationActions(stmt, TYPE_FUNC(cscope_currentfunc->type)->exspecs); - } -} |