summaryrefslogtreecommitdiff
path: root/compiler_and_linker/BackEnd/PowerPC/CodeGenerator/Exceptions.c
diff options
context:
space:
mode:
Diffstat (limited to 'compiler_and_linker/BackEnd/PowerPC/CodeGenerator/Exceptions.c')
-rw-r--r--compiler_and_linker/BackEnd/PowerPC/CodeGenerator/Exceptions.c857
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);
+}