mirror of https://git.wuffs.org/MWCC
858 lines
31 KiB
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);
|
|
}
|