MWCC/compiler_and_linker/unsorted/Exceptions.c

858 lines
31 KiB
C

#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);
}