diff options
Diffstat (limited to 'compiler_and_linker/BackEnd/PowerPC/CodeGenerator/Exceptions.c')
-rw-r--r-- | compiler_and_linker/BackEnd/PowerPC/CodeGenerator/Exceptions.c | 857 |
1 files changed, 857 insertions, 0 deletions
diff --git a/compiler_and_linker/BackEnd/PowerPC/CodeGenerator/Exceptions.c b/compiler_and_linker/BackEnd/PowerPC/CodeGenerator/Exceptions.c new file mode 100644 index 0000000..14627cf --- /dev/null +++ b/compiler_and_linker/BackEnd/PowerPC/CodeGenerator/Exceptions.c @@ -0,0 +1,857 @@ +#include "compiler/Exceptions.h" +#include "compiler/CError.h" +#include "compiler/CException.h" +#include "compiler/CInit.h" +#include "compiler/CFunc.h" +#include "compiler/CParser.h" +#include "compiler/CompilerTools.h" +#include "compiler/ObjGenMachO.h" +#include "compiler/PCode.h" +#include "compiler/PCodeUtilities.h" +#include "compiler/RegisterInfo.h" +#include "compiler/StackFrame.h" +#include "compiler/objects.h" + +static PCAction *pc_actions; +static PCAction *last_pc_action; +EANode *DAG[EAT_NACTIONS]; +static GList exceptmodule; +static OLinkList *except_refs; +static OLinkList *last_except_ref; + +static EANode *makeEAnode(ExceptionAction *ea) { + EANode *prev; + EANode *node; + + for (node = DAG[ea->type]; node; node = node->dagListNext) { + if (node->action == ea) + return node; + } + + if (ea->prev) + prev = makeEAnode(ea->prev); + else + prev = NULL; + + for (node = DAG[ea->type]; node; node = node->dagListNext) { + if (node->prev == prev && CExcept_ActionCompare(node->action, ea)) + return node; + } + + node = lalloc(sizeof(EANode)); + node->prev = prev; + node->action = ea; + node->count = 0; + node->xE = 0; + + node->dagListNext = DAG[ea->type]; + DAG[ea->type] = node; + + if (prev) + prev->count++; + return node; +} + +static void addrelocation(Object *obj, SInt32 offset) { + OLinkList *ref; + + ref = lalloc(sizeof(OLinkList)); + ref->next = NULL; + ref->obj = obj; + ref->offset = offset; + ref->somevalue = 0; + if (except_refs) + last_except_ref->next = ref; + else + except_refs = ref; + last_except_ref = ref; +} + +#ifdef __MWERKS__ +#pragma options align=mac68k +#endif +typedef struct AABC { + UInt8 a; + UInt8 b; + UInt16 c; + UInt32 d; +} AABC; + +typedef struct AACC { + UInt8 a; + UInt8 b; + UInt32 c; + UInt32 d; +} AACC; + +typedef struct AABBC { + UInt8 a; + UInt8 b; + UInt16 c; + UInt16 d; + UInt32 e; +} AABBC; + +typedef struct AABCC { + UInt8 a; + UInt8 b; + UInt16 c; + UInt32 d; + UInt32 e; +} AABCC; + +typedef struct AACCC { + UInt8 a; + UInt8 b; + UInt32 c; + UInt32 d; + UInt32 e; +} AACCC; + +typedef struct AABBBC { + UInt8 a; + UInt8 b; + UInt16 c; + UInt16 d; + UInt16 e; + UInt32 f; +} AABBBC; + +typedef struct AABBCC { + UInt8 a; + UInt8 b; + UInt16 c; + UInt16 d; + UInt32 e; + UInt32 f; +} AABBCC; + +typedef struct AACCCC { + UInt8 a; + UInt8 b; + UInt32 c; + UInt32 d; + UInt32 e; + UInt32 f; +} AACCCC; + +typedef struct AABCCCC { + UInt8 a; + UInt8 b; + UInt16 c; + UInt32 d; + UInt32 e; + UInt32 f; + UInt32 g; +} AABCCCC; + +typedef struct AACCCCC { + UInt8 a; + UInt8 b; + UInt32 c; + UInt32 d; + UInt32 e; + UInt32 f; + UInt32 g; +} AACCCCC; + +typedef struct AAB { + UInt8 a; + UInt8 b; + UInt16 c; +} AAB; + +typedef struct AAC { + UInt8 a; + UInt8 b; + UInt32 c; +} AAC; + +typedef struct AA { + UInt8 a; + UInt8 b; +} AA; +#ifdef __MWERKS__ +#pragma options align=reset +#endif + +static void allocateactioninfo(EANode *node) { + ExceptionAction *ea; + SInt32 offset; + UInt32 flag26; + int reg; + int reg2; + + while (node && (node->xE == 0 || node->prev == NULL)) { + offset = exceptmodule.size; + if (node->xE == 0) + node->xE = offset; + + flag26 = node->prev ? 0 : 0x80; + + ea = node->action; + + switch (ea->type) { + case EAT_NOP: + CError_FATAL(146); + break; + case EAT_DESTROYLOCAL: { + if (local_is_16bit_offset(ea->data.destroy_local.local)) { + AABC e; + e.a = flag26 | 2; + e.b = 0; + e.c = CTool_EndianConvertWord16(local_offset_16(ea->data.destroy_local.local)); + e.d = 0; + AppendGListData(&exceptmodule, &e, sizeof(e)); + addrelocation(ea->data.destroy_local.dtor, offset + 4); + } else { + AACC e; + e.a = flag26 | 0x11; + e.b = 0; + e.c = CTool_EndianConvertWord32(local_offset_32(ea->data.destroy_local.local)); + e.d = 0; + AppendGListData(&exceptmodule, &e, sizeof(e)); + addrelocation(ea->data.destroy_local.dtor, offset + 6); + } + break; + } + case EAT_DESTROYLOCALCOND: { + reg = OBJECT_REG(ea->data.destroy_local_cond.cond); + if ( + (reg || local_is_16bit_offset(ea->data.destroy_local_cond.cond)) && + local_is_16bit_offset(ea->data.destroy_local_cond.local) + ) + { + AABBC e; + e.a = flag26 | 3; + e.b = (reg != 0) << 7; + e.c = CTool_EndianConvertWord16(reg ? reg : local_offset_16(ea->data.destroy_local_cond.cond)); + e.d = CTool_EndianConvertWord16(local_offset_16(ea->data.destroy_local_cond.local)); + e.e = 0; + AppendGListData(&exceptmodule, &e, sizeof(e)); + addrelocation(ea->data.destroy_local_cond.dtor, offset + 6); + } else { + AACCC e; + e.a = flag26 | 0x12; + e.b = (reg != 0) << 7; + e.c = CTool_EndianConvertWord32(reg ? reg : local_offset_32(ea->data.destroy_local_cond.cond)); + e.d = CTool_EndianConvertWord32(local_offset_32(ea->data.destroy_local_cond.local)); + e.e = 0; + AppendGListData(&exceptmodule, &e, sizeof(e)); + addrelocation(ea->data.destroy_local_cond.dtor, offset + 10); + } + break; + } + case EAT_DESTROYLOCALOFFSET: { + if (local_is_16bit_offset(ea->data.destroy_local_offset.local)) { + AABC e; + e.a = flag26 | 2; + e.b = 0; + e.c = CTool_EndianConvertWord16(ea->data.destroy_local_offset.offset + local_offset_16(ea->data.destroy_local_offset.local)); + e.d = 0; + AppendGListData(&exceptmodule, &e, sizeof(e)); + addrelocation(ea->data.destroy_local_offset.dtor, offset + 4); + } else { + AACC e; + e.a = flag26 | 0x11; + e.b = 0; + e.c = CTool_EndianConvertWord32(ea->data.destroy_local_offset.offset + local_offset_32(ea->data.destroy_local_offset.local)); + e.d = 0; + AppendGListData(&exceptmodule, &e, sizeof(e)); + addrelocation(ea->data.destroy_local_offset.dtor, offset + 6); + } + break; + } + case EAT_DESTROYLOCALPOINTER: { + reg = OBJECT_REG(ea->data.destroy_local_pointer.pointer); + if (reg || local_is_16bit_offset(ea->data.destroy_local_pointer.pointer)) { + AABC e; + e.a = flag26 | 4; + e.b = (reg != 0) << 7; + e.c = CTool_EndianConvertWord16(reg ? reg : local_offset_16(ea->data.destroy_local_pointer.pointer)); + e.d = 0; + AppendGListData(&exceptmodule, &e, sizeof(e)); + addrelocation(ea->data.destroy_local_pointer.dtor, offset + 4); + } else { + AACC e; + e.a = flag26 | 0x13; + e.b = (reg != 0) << 7; + e.c = CTool_EndianConvertWord32(reg ? reg : local_offset_32(ea->data.destroy_local_pointer.pointer)); + e.d = 0; + AppendGListData(&exceptmodule, &e, sizeof(e)); + addrelocation(ea->data.destroy_local_pointer.dtor, offset + 6); + } + break; + } + case EAT_DESTROYLOCALARRAY: { + if (local_is_16bit_offset(ea->data.destroy_local_array.localarray)) { + AABBBC e; + e.a = flag26 | 5; + e.b = 0; + e.c = CTool_EndianConvertWord16(local_offset_16(ea->data.destroy_local_array.localarray)); + e.d = CTool_EndianConvertWord16(ea->data.destroy_local_array.elements); + e.e = CTool_EndianConvertWord16(ea->data.destroy_local_array.element_size); + e.f = 0; + AppendGListData(&exceptmodule, &e, sizeof(e)); + addrelocation(ea->data.destroy_local_array.dtor, offset + 8); + } else { + AACCCC e; + e.a = flag26 | 0x14; + e.b = 0; + e.c = CTool_EndianConvertWord32(local_offset_32(ea->data.destroy_local_array.localarray)); + e.d = CTool_EndianConvertWord32(ea->data.destroy_local_array.elements); + e.e = CTool_EndianConvertWord32(ea->data.destroy_local_array.element_size); + e.f = 0; + AppendGListData(&exceptmodule, &e, sizeof(e)); + addrelocation(ea->data.destroy_local_array.dtor, offset + 14); + } + break; + } + case EAT_DESTROYMEMBER: { + reg = OBJECT_REG(ea->data.destroy_member.objectptr); + if (reg || local_is_16bit_offset(ea->data.destroy_member.objectptr)) { + AABCC e; + e.a = flag26 | 7; + e.b = (reg != 0) << 7; + e.c = CTool_EndianConvertWord16(reg ? reg : local_offset_16(ea->data.destroy_member.objectptr)); + e.d = CTool_EndianConvertWord32(ea->data.destroy_member.offset); + e.e = 0; + AppendGListData(&exceptmodule, &e, sizeof(e)); + addrelocation(ea->data.destroy_member.dtor, offset + 8); + } else { + AACCC e; + e.a = flag26 | 0x16; + e.b = (reg != 0) << 7; + e.c = CTool_EndianConvertWord32(reg ? reg : local_offset_32(ea->data.destroy_member.objectptr)); + e.d = CTool_EndianConvertWord32(ea->data.destroy_member.offset); + e.e = 0; + AppendGListData(&exceptmodule, &e, sizeof(e)); + addrelocation(ea->data.destroy_member.dtor, offset + 10); + } + break; + } + case EAT_DESTROYBASE: { + reg = OBJECT_REG(ea->data.destroy_member.objectptr); + if (reg || local_is_16bit_offset(ea->data.destroy_member.objectptr)) { + AABCC e; + e.a = flag26 | 6; + e.b = (reg != 0) << 7; + e.c = CTool_EndianConvertWord16(reg ? reg : local_offset_16(ea->data.destroy_member.objectptr)); + e.d = CTool_EndianConvertWord32(ea->data.destroy_member.offset); + e.e = 0; + AppendGListData(&exceptmodule, &e, sizeof(e)); + addrelocation(ea->data.destroy_member.dtor, offset + 8); + } else { + AACCC e; + e.a = flag26 | 0x15; + e.b = (reg != 0) << 7; + e.c = CTool_EndianConvertWord32(reg ? reg : local_offset_32(ea->data.destroy_member.objectptr)); + e.d = CTool_EndianConvertWord32(ea->data.destroy_member.offset); + e.e = 0; + AppendGListData(&exceptmodule, &e, sizeof(e)); + addrelocation(ea->data.destroy_member.dtor, offset + 10); + } + break; + } + case EAT_DESTROYMEMBERCOND: { + reg = OBJECT_REG(ea->data.destroy_member_cond.cond); + reg2 = OBJECT_REG(ea->data.destroy_member_cond.objectptr); + if ( + (reg || local_is_16bit_offset(ea->data.destroy_member_cond.cond)) && + (reg2 || local_is_16bit_offset(ea->data.destroy_member_cond.objectptr)) + ) + { + AABBCC e; + e.a = flag26 | 8; + e.b = ((reg ? 1 : 0) << 7) | ((reg2 ? 1 : 0) << 6); + e.c = CTool_EndianConvertWord16(reg ? reg : local_offset_16(ea->data.destroy_member_cond.cond)); + e.d = CTool_EndianConvertWord16(reg2 ? reg2 : local_offset_16(ea->data.destroy_member_cond.objectptr)); + e.e = CTool_EndianConvertWord32(ea->data.destroy_member_cond.offset); + e.f = 0; + AppendGListData(&exceptmodule, &e, sizeof(e)); + addrelocation(ea->data.destroy_member_cond.dtor, offset + 10); + } else { + AACCCC e; + e.a = flag26 | 0x17; + e.b = ((reg ? 1 : 0) << 7) | ((reg2 ? 1 : 0) << 6); + e.c = CTool_EndianConvertWord32(reg ? reg : local_offset_32(ea->data.destroy_member_cond.cond)); + e.d = CTool_EndianConvertWord32(reg2 ? reg2 : local_offset_32(ea->data.destroy_member_cond.objectptr)); + e.e = CTool_EndianConvertWord32(ea->data.destroy_member_cond.offset); + e.f = 0; + AppendGListData(&exceptmodule, &e, sizeof(e)); + addrelocation(ea->data.destroy_member_cond.dtor, offset + 14); + } + break; + } + case EAT_DESTROYMEMBERARRAY: { + reg = OBJECT_REG(ea->data.destroy_member_array.objectptr); + if (reg || local_is_16bit_offset(ea->data.destroy_member_array.objectptr)) { + AABCCCC e; + e.a = flag26 | 9; + e.b = (reg != 0) << 7; + e.c = CTool_EndianConvertWord16(reg ? reg : local_offset_16(ea->data.destroy_member_array.objectptr)); + e.d = CTool_EndianConvertWord32(ea->data.destroy_member_array.offset); + e.e = CTool_EndianConvertWord32(ea->data.destroy_member_array.elements); + e.f = CTool_EndianConvertWord32(ea->data.destroy_member_array.element_size); + e.g = 0; + AppendGListData(&exceptmodule, &e, sizeof(e)); + addrelocation(ea->data.destroy_member_array.dtor, offset + 16); + } else { + AACCCCC e; + e.a = flag26 | 0x18; + e.b = (reg != 0) << 7; + e.c = CTool_EndianConvertWord32(reg ? reg : local_offset_32(ea->data.destroy_member_array.objectptr)); + e.d = CTool_EndianConvertWord32(ea->data.destroy_member_array.offset); + e.e = CTool_EndianConvertWord32(ea->data.destroy_member_array.elements); + e.f = CTool_EndianConvertWord32(ea->data.destroy_member_array.element_size); + e.g = 0; + AppendGListData(&exceptmodule, &e, sizeof(e)); + addrelocation(ea->data.destroy_member_array.dtor, offset + 18); + } + break; + } + case EAT_DELETEPOINTER: + case EAT_DELETELOCALPOINTER: { + reg = OBJECT_REG(ea->data.delete_pointer.pointerobject); + if (reg || local_is_16bit_offset(ea->data.delete_pointer.pointerobject)) { + AABC e; + e.a = flag26 | 0xA; + e.b = (reg != 0) << 7; + e.c = CTool_EndianConvertWord16(reg ? reg : local_offset_16(ea->data.delete_pointer.pointerobject)); + e.d = 0; + AppendGListData(&exceptmodule, &e, sizeof(e)); + addrelocation(ea->data.delete_pointer.deletefunc, offset + 4); + } else { + AACC e; + e.a = flag26 | 0x19; + e.b = (reg != 0) << 7; + e.c = CTool_EndianConvertWord32(reg ? reg : local_offset_32(ea->data.delete_pointer.pointerobject)); + e.d = 0; + AppendGListData(&exceptmodule, &e, sizeof(e)); + addrelocation(ea->data.delete_pointer.deletefunc, offset + 6); + } + break; + } + case EAT_DELETEPOINTERCOND: { + reg = OBJECT_REG(ea->data.delete_pointer_cond.cond); + reg2 = OBJECT_REG(ea->data.delete_pointer_cond.pointerobject); + if ( + (reg || local_is_16bit_offset(ea->data.delete_pointer_cond.cond)) && + (reg2 || local_is_16bit_offset(ea->data.delete_pointer_cond.pointerobject)) + ) + { + AABBC e; + e.a = flag26 | 0xB; + e.b = ((reg ? 1 : 0) << 7) | ((reg2 ? 1 : 0) << 6); + e.c = CTool_EndianConvertWord16(reg ? reg : local_offset_16(ea->data.delete_pointer_cond.cond)); + e.d = CTool_EndianConvertWord16(reg2 ? reg2 : local_offset_16(ea->data.delete_pointer_cond.pointerobject)); + e.e = 0; + AppendGListData(&exceptmodule, &e, sizeof(e)); + addrelocation(ea->data.delete_pointer_cond.deletefunc, offset + 6); + } else { + AACCC e; + e.a = flag26 | 0x1A; + e.b = ((reg ? 1 : 0) << 7) | ((reg2 ? 1 : 0) << 6); + e.c = CTool_EndianConvertWord32(reg ? reg : local_offset_32(ea->data.delete_pointer_cond.cond)); + e.d = CTool_EndianConvertWord32(reg2 ? reg2 : local_offset_32(ea->data.delete_pointer_cond.pointerobject)); + e.e = 0; + AppendGListData(&exceptmodule, &e, sizeof(e)); + addrelocation(ea->data.delete_pointer_cond.deletefunc, offset + 10); + } + break; + } + case EAT_CATCHBLOCK: { + AACCC e; + e.a = flag26 | 0x10; + e.b = 0; + e.c = 0; + if (ea->data.catch_block.catch_label->pclabel) + e.d = CTool_EndianConvertWord32(ea->data.catch_block.catch_label->pclabel->block->codeOffset); + else + e.d = 0; + e.e = CTool_EndianConvertWord32(local_offset_16(ea->data.catch_block.catch_info_object)); + AppendGListData(&exceptmodule, &e, sizeof(e)); + if (ea->data.catch_block.catch_typeid) + addrelocation(ea->data.catch_block.catch_typeid, offset + 2); + break; + } + case EAT_ACTIVECATCHBLOCK: { + if (local_is_16bit_offset(ea->data.active_catch_block.catch_info_object)) { + AAB e; + e.a = flag26 | 0xD; + e.b = 0; + e.c = CTool_EndianConvertWord16(local_offset_16(ea->data.active_catch_block.catch_info_object)); + AppendGListData(&exceptmodule, &e, sizeof(e)); + } else { + AAC e; + e.a = flag26 | 0x1B; + e.b = 0; + e.c = CTool_EndianConvertWord32(local_offset_32(ea->data.active_catch_block.catch_info_object)); + AppendGListData(&exceptmodule, &e, sizeof(e)); + } + break; + } + case EAT_SPECIFICATION: { + AABCC e; + int i; + + e.a = flag26 | 0xF; + e.b = 0; + e.c = CTool_EndianConvertWord16(ea->data.specification.unexp_ids); + if (ea->data.specification.unexp_label->pclabel) + e.d = CTool_EndianConvertWord32(ea->data.specification.unexp_label->pclabel->block->codeOffset); + e.e = CTool_EndianConvertWord32(local_offset_16(ea->data.specification.unexp_info_object)); + AppendGListData(&exceptmodule, &e, sizeof(e)); + + for (i = 0; i < ea->data.specification.unexp_ids; i++) { + addrelocation(ea->data.specification.unexp_id[i], 12 + i * 4 + offset); + AppendGListLong(&exceptmodule, 0); + } + break; + } + case EAT_TERMINATE: { + AA e; + e.a = flag26 | 0xE; + e.b = 0; + AppendGListData(&exceptmodule, &e, sizeof(e)); + break; + } + default: + CError_FATAL(671); + } + + node = node->prev; + } + + if (node) { + AAB e; + e.a = 1; + e.b = 0; + e.c = CTool_EndianConvertWord16(node->xE); + AppendGListData(&exceptmodule, &e, sizeof(e)); + } +} + +static UInt32 findPC(PCode *instr) { + UInt32 pc = instr->block->codeOffset; + instr = instr->prevPCode; + while (instr) { + instr = instr->prevPCode; + pc += 4; + } + CError_ASSERT(704, FITS_IN_USHORT(pc)); + return pc; +} + +static UInt32 findPC_long(PCode *instr) { + UInt32 pc = instr->block->codeOffset; + instr = instr->prevPCode; + while (instr) { + instr = instr->prevPCode; + pc += 4; + } + return pc; +} + +void initializeexceptiontables(void) { + int i; + + for (i = 0; i < EAT_NACTIONS; i++) + DAG[i] = NULL; + + pc_actions = last_pc_action = NULL; + except_refs = last_except_ref = NULL; +} + +int countexceptionactionregisters(ExceptionAction *actions) { + int count = 0; + + while (actions) { + switch (actions->type) { + case EAT_DESTROYLOCALCOND: + if (OBJECT_REG(actions->data.destroy_local_cond.cond)) + count++; + break; + case EAT_DESTROYLOCALPOINTER: + if (OBJECT_REG(actions->data.destroy_local_pointer.pointer)) + count++; + break; + case EAT_DESTROYMEMBER: + if (OBJECT_REG(actions->data.destroy_member.objectptr)) + count++; + break; + case EAT_DESTROYBASE: + if (OBJECT_REG(actions->data.destroy_base.objectptr)) + count++; + break; + case EAT_DESTROYMEMBERCOND: + if (OBJECT_REG(actions->data.destroy_member_cond.cond)) + count++; + if (OBJECT_REG(actions->data.destroy_member_cond.objectptr)) + count++; + break; + case EAT_DESTROYMEMBERARRAY: + if (OBJECT_REG(actions->data.destroy_member_array.objectptr)) + count++; + break; + case EAT_DELETEPOINTER: + case EAT_DELETELOCALPOINTER: + if (OBJECT_REG(actions->data.delete_pointer.pointerobject)) + count++; + break; + case EAT_DELETEPOINTERCOND: + if (OBJECT_REG(actions->data.delete_pointer_cond.cond)) + count++; + if (OBJECT_REG(actions->data.delete_pointer_cond.pointerobject)) + count++; + break; + } + actions = actions->prev; + } + + return count; +} + +void noteexceptionactionregisters(ExceptionAction *actions, PCodeArg *ops) { + Object *obj; + int reg; + + while (actions) { + switch (actions->type) { + case EAT_DESTROYLOCALCOND: + if ((reg = OBJECT_REG(obj = actions->data.destroy_local_cond.cond))) { + ops->kind = PCOp_REGISTER; + ops->arg = obj->u.var.info->rclass; + ops->data.reg.reg = reg; + ops->data.reg.effect = EffectRead | Effect8; + ops++; + } + break; + case EAT_DESTROYLOCALPOINTER: + if ((reg = OBJECT_REG(obj = actions->data.destroy_local_pointer.pointer))) { + ops->kind = PCOp_REGISTER; + ops->arg = obj->u.var.info->rclass; + ops->data.reg.reg = reg; + ops->data.reg.effect = EffectRead | Effect8; + ops++; + } + break; + case EAT_DESTROYMEMBER: + if ((reg = OBJECT_REG(obj = actions->data.destroy_member.objectptr))) { + ops->kind = PCOp_REGISTER; + ops->arg = obj->u.var.info->rclass; + ops->data.reg.reg = reg; + ops->data.reg.effect = EffectRead | Effect8; + ops++; + } + break; + case EAT_DESTROYBASE: + if ((reg = OBJECT_REG(obj = actions->data.destroy_base.objectptr))) { + ops->kind = PCOp_REGISTER; + ops->arg = obj->u.var.info->rclass; + ops->data.reg.reg = reg; + ops->data.reg.effect = EffectRead | Effect8; + ops++; + } + break; + case EAT_DESTROYMEMBERCOND: + if ((reg = OBJECT_REG(obj = actions->data.destroy_member_cond.cond))) { + ops->kind = PCOp_REGISTER; + ops->arg = obj->u.var.info->rclass; + ops->data.reg.reg = reg; + ops->data.reg.effect = EffectRead | Effect8; + ops++; + } + if ((reg = OBJECT_REG(obj = actions->data.destroy_member_cond.objectptr))) { + ops->kind = PCOp_REGISTER; + ops->arg = obj->u.var.info->rclass; + ops->data.reg.reg = reg; + ops->data.reg.effect = EffectRead | Effect8; + ops++; + } + break; + case EAT_DESTROYMEMBERARRAY: + if ((reg = OBJECT_REG(obj = actions->data.destroy_member_array.objectptr))) { + ops->kind = PCOp_REGISTER; + ops->arg = obj->u.var.info->rclass; + ops->data.reg.reg = reg; + ops->data.reg.effect = EffectRead | Effect8; + ops++; + } + break; + case EAT_DELETEPOINTER: + case EAT_DELETELOCALPOINTER: + if ((reg = OBJECT_REG(obj = actions->data.delete_pointer.pointerobject))) { + ops->kind = PCOp_REGISTER; + ops->arg = obj->u.var.info->rclass; + ops->data.reg.reg = reg; + ops->data.reg.effect = EffectRead | Effect8; + ops++; + } + break; + case EAT_DELETEPOINTERCOND: + if ((reg = OBJECT_REG(obj = actions->data.delete_pointer_cond.cond))) { + ops->kind = PCOp_REGISTER; + ops->arg = obj->u.var.info->rclass; + ops->data.reg.reg = reg; + ops->data.reg.effect = EffectRead | Effect8; + ops++; + } + if ((reg = OBJECT_REG(obj = actions->data.delete_pointer_cond.pointerobject))) { + ops->kind = PCOp_REGISTER; + ops->arg = obj->u.var.info->rclass; + ops->data.reg.reg = reg; + ops->data.reg.effect = EffectRead | Effect8; + ops++; + } + break; + } + actions = actions->prev; + } +} + +void recordexceptionactions(PCode *instr, ExceptionAction *actions) { + PCAction *pca; + + if (!actions && (!last_pc_action || !last_pc_action->actions)) + return; + + pca = lalloc(sizeof(PCAction)); + pca->next = NULL; + pca->firstInstr = pca->lastInstr = instr; + pca->actions = actions; + pca->prev = last_pc_action; + if (last_pc_action) + last_pc_action->next = pca; + else + pc_actions = pca; + last_pc_action = pca; + + branch_label(makepclabel()); + while (actions) { + if (actions->type == EAT_CATCHBLOCK && actions->data.catch_block.catch_label->pclabel) + pcbranch(instr->block, actions->data.catch_block.catch_label->pclabel); + else if (actions->type == EAT_SPECIFICATION && actions->data.specification.unexp_label->pclabel) + pcbranch(instr->block, actions->data.specification.unexp_label->pclabel); + actions = actions->prev; + } +} + +static void deleteexceptionaction(PCAction *pca) { + if (pca->prev) + pca->prev->next = pca->next; + else + pc_actions = pca->next; + + if (pca->next) + pca->next->prev = pca->prev; +} + +static int mergeexceptionactions(void) { + int count; + PCAction *pca; + PCAction *prev; + + if (!pc_actions) + return 0; + + for (pca = pc_actions; pca; pca = pca->next) { + if (pca->firstInstr->block->flags & fDeleted) + deleteexceptionaction(pca); + } + + if (!(pca = pc_actions)) + return 0; + + while (pca) { + pca->node = pca->actions ? makeEAnode(pca->actions) : NULL; + pca = pca->next; + } + + prev = pc_actions; + for (pca = pc_actions->next; pca; pca = pca->next) { + if (pca->node == prev->node) { + prev->lastInstr = pca->lastInstr; + deleteexceptionaction(pca); + } else { + prev = pca; + } + } + + count = 0; + for (pca = pc_actions; pca; pca = pca->next) { + if (!pca->actions) + deleteexceptionaction(pca); + else + count++; + } + + return count; +} + +typedef struct ExceptionThing { + UInt32 x0; + UInt16 x4; + UInt16 x6; +} ExceptionThing; + +void dumpexceptiontables(Object *function, SInt32 codesize) { + PCAction *pca; + UInt32 insn_start; + UInt32 insn_count; + UInt16 *sh; + ExceptionThing *thing; + int count; + + count = mergeexceptionactions(); + InitGList(&exceptmodule, 256); + AppendGListNoData(&exceptmodule, 8 * count + 4); + AppendGListLong(&exceptmodule, 0); + + for (pca = pc_actions; pca; pca = pca->next) { + if (pca->node->count == 0 && pca->node->xE == 0) + allocateactioninfo(pca->node); + } + + sh = (UInt16 *) *exceptmodule.data; + if (copts.altivec_model && used_nonvolatile_registers[RegClass_VR]) { + sh[0] = + CTool_EndianConvertWord16( + (used_nonvolatile_registers[RegClass_GPR] << 11) | + ((used_nonvolatile_registers[RegClass_FPR] & 0x1F) << 6) | + (((used_nonvolatile_registers[RegClass_CRFIELD] != 0) & 1) << 5) | + ((dynamic_stack & 1) << 4) | + 8); + sh[0] |= 4; + if (copts.altivec_vrsave) + sh[1] = CTool_EndianConvertWord16((used_nonvolatile_registers[RegClass_VR] << 11) | 0x400); + else + sh[1] = CTool_EndianConvertWord16((used_nonvolatile_registers[RegClass_VR] & 0x1F) << 11); + } else { + sh[0] = + CTool_EndianConvertWord16( + (used_nonvolatile_registers[RegClass_GPR] << 11) | + ((used_nonvolatile_registers[RegClass_FPR] & 0x1F) << 6) | + (((used_nonvolatile_registers[RegClass_CRFIELD] != 0) & 1) << 5) | + ((dynamic_stack & 1) << 4) | + 8); + sh[1] = 0; + } + + thing = (ExceptionThing *) (sh + 2); + pca = pc_actions; + while (pca) { + insn_start = findPC_long(pca->firstInstr); + insn_count = (findPC_long(pca->lastInstr) - insn_start) / 4; + CError_ASSERT(1203, (insn_count & 0xFFFF0000) == 0); + thing->x0 = CTool_EndianConvertWord32(insn_start + 4); + thing->x4 = CTool_EndianConvertWord16(insn_count); + thing->x6 = CTool_EndianConvertWord16(pca->node->xE); + pca = pca->next; + thing++; + } + + LockGList(&exceptmodule); + ObjGen_DeclareExceptionTables(function, codesize, *exceptmodule.data, exceptmodule.size, except_refs); + FreeGList(&exceptmodule); +} |