diff options
Diffstat (limited to 'compiler_and_linker/FrontEnd/Common/CIRTransform.c')
-rw-r--r-- | compiler_and_linker/FrontEnd/Common/CIRTransform.c | 534 |
1 files changed, 534 insertions, 0 deletions
diff --git a/compiler_and_linker/FrontEnd/Common/CIRTransform.c b/compiler_and_linker/FrontEnd/Common/CIRTransform.c new file mode 100644 index 0000000..b91f6af --- /dev/null +++ b/compiler_and_linker/FrontEnd/Common/CIRTransform.c @@ -0,0 +1,534 @@ +#include "compiler/CIRTransform.h" +#include "compiler/CError.h" +#include "compiler/CExpr.h" +#include "compiler/CFunc.h" +#include "compiler/CInit.h" +#include "compiler/CMachine.h" +#include "compiler/CParser.h" +#include "compiler/objects.h" +#include "compiler/types.h" +#include "compiler/CompilerTools.h" +#include "compiler/CDecl.h" + +#ifdef __MWERKS__ +#pragma options align=mac68k +#endif +typedef struct CIRTransTemp { + struct CIRTransTemp *next; + Object *object; + Boolean flag; +} CIRTransTemp; + +typedef struct MultiAccessOperand { + Object *object; + Object *tempobj; + ENode *ass; + Type *type; + Type *bitfieldType; +} MultiAccessOperand; + +// no idea what this is for... +typedef struct StrangeRuntimeFunction { + Object *object; + short unk; + char name[1]; +} StrangeRuntimeFunction; +#ifdef __MWERKS__ +#pragma options align=reset +#endif + +static TypeFunc cirtrans_rtfunc8 = { + TYPEFUNC, 0, NULL, NULL, TYPE(&void_ptr), 0, 0 +}; +static TypeFunc cirtrans_rtfunc4 = { + TYPEFUNC, 0, NULL, NULL, TYPE(&stunsignedlong), 0, 0 +}; +static TypeFunc cirtrans_rtfunc2 = { + TYPEFUNC, 0, NULL, NULL, TYPE(&stsignedshort), 0, 0 +}; + +static CIRTransTemp *cirtrans_temps; +Boolean modulo_generated; +Boolean bigswitch_generated; +Boolean alloca_called; + +// forward decls +static ENode *CIRTrans_TransExpr(ENode *expr, Boolean flag); + +void CIRTrans_Setup(void) { +} + +void CIRTrans_Cleanup(void) { +} + +static Object *CIRTrans_GetRuntimeFunction(StrangeRuntimeFunction *rtfunc, Type *type) { + Object *object; + + object = rtfunc->object; + if (!object) { + object = CParser_NewFunctionObject(NULL); + rtfunc->object = object; + + object->nspace = cscope_root; + object->name = GetHashNameNodeExport(rtfunc->name); + object->flags = OBJECT_INTERNAL; + + if (type) { + switch (type->size) { + case 2: + object->type = TYPE(&cirtrans_rtfunc2); + break; + case 4: + object->type = TYPE(&cirtrans_rtfunc4); + break; + case 8: + object->type = TYPE(&cirtrans_rtfunc8); + break; + default: + CError_FATAL(427); + } + } else { + object->type = TYPE(&cirtrans_rtfunc8); + } + } + + return object; +} + +static Object *CIRTrans_GetTemporary(Type *type) { + CIRTransTemp *temp; + + for (temp = cirtrans_temps; temp; temp = temp->next) { + if (temp->object->type->size == type->size && !temp->flag) { + temp->flag = 1; + return temp->object; + } + } + + temp = oalloc(sizeof(CIRTransTemp)); + temp->next = cirtrans_temps; + cirtrans_temps = temp; + + temp->object = create_temp_object(type); + temp->flag = 1; + return temp->object; +} + +static ENode *CIRTrans_CheckRuntimeAssign(ENode *expr) { + ENode *inner; + + if (ENODE_IS(expr->data.diadic.right, EINDIRECT)) { + inner = expr->data.diadic.right->data.monadic; + if ( + ENODE_IS(inner, EFUNCCALL) && + (inner->flags & ENODE_FLAG_80) && + inner->data.funccall.args && + ENODE_IS(inner->data.funccall.args->node, EOBJREF) + ) + { + CError_ASSERT(502, ENODE_IS(expr->data.diadic.left, EINDIRECT)); + inner->data.funccall.args->node = expr->data.diadic.left->data.monadic; + inner->flags &= ~ENODE_FLAG_80; + return expr->data.diadic.right; + } + } + + return expr; +} + +static void CIRTrans_SetupMultiAccessOperand(MultiAccessOperand *mop, ENode *expr) { + memclrw(mop, sizeof(MultiAccessOperand)); + + mop->type = expr->rtype; + + CError_ASSERT(522, ENODE_IS(expr, EINDIRECT)); + expr = expr->data.monadic; + + if (ENODE_IS(expr, EOBJREF)) { + mop->object = expr->data.objref; + } else { + if (ENODE_IS(expr, EBITFIELD)) { + mop->bitfieldType = expr->rtype; + expr = expr->data.monadic; + } + expr->rtype = CDecl_NewPointerType(mop->type); + mop->tempobj = create_temp_object(expr->rtype); + mop->ass = makediadicnode(create_objectnode(mop->tempobj), expr, EASS); + } +} + +static ENode *CIRTrans_GetMultiAccessOperand(MultiAccessOperand *mop) { + ENode *expr; + + if (mop->object == NULL) { + expr = create_objectnode(mop->tempobj); + if (mop->bitfieldType) { + expr = makemonadicnode(expr, EBITFIELD); + expr->rtype = mop->bitfieldType; + } + expr = makemonadicnode(expr, EINDIRECT); + } else { + expr = create_objectnode(mop->object); + } + + expr->rtype = mop->type; + return expr; +} + +static ENode *CIRTrans_InitMultiAccessExpression(MultiAccessOperand *mop, ENode *expr) { + if (mop->ass) { + expr = makediadicnode(mop->ass, expr, ECOMMA); + expr->rtype = expr->data.diadic.right->rtype; + } + return expr; +} + +ENode *CIRTrans_TransformOpAss(ENode *expr) { + ENodeType nt; + ENode *expr2; + MultiAccessOperand mop; + + if (!ENODE_IS(expr->data.diadic.left, EINDIRECT)) { + CError_Error(CErrorStr142); + return nullnode(); + } + + CIRTrans_SetupMultiAccessOperand(&mop, expr->data.diadic.left); + + switch (expr->type) { + case EMULASS: + nt = EMUL; + break; + case EDIVASS: + nt = EDIV; + break; + case EMODASS: + nt = EMODULO; + break; + case EADDASS: + nt = EADD; + break; + case ESUBASS: + nt = ESUB; + break; + case ESHLASS: + nt = ESHL; + break; + case ESHRASS: + nt = ESHR; + break; + case EANDASS: + nt = EAND; + break; + case EXORASS: + nt = EXOR; + break; + case EORASS: + nt = EOR; + break; + default: + CError_FATAL(622); + } + + expr2 = CIRTrans_GetMultiAccessOperand(&mop); + + if (!IS_TYPE_POINTER_ONLY(expr2->rtype)) { + expr2 = CExpr_NewDyadicNode(expr2, nt, expr->data.diadic.right); + if (expr2->rtype != expr->data.diadic.left->rtype) { + expr2 = makemonadicnode(expr2, ETYPCON); + expr2->rtype = expr->data.diadic.left->rtype; + } + } else { + expr2 = makediadicnode(expr2, expr->data.diadic.right, nt); + } + + if (IS_TYPE_FLOAT(expr2->rtype)) + expr2 = CExpr_BinaryFloatExpression(expr2); + + expr2 = makediadicnode(CIRTrans_GetMultiAccessOperand(&mop), expr2, EASS); + return CIRTrans_InitMultiAccessExpression(&mop, expr2); +} + +static void CIRTrans_TransIncDec() { + // empty, never called +} + +static ENode *CIRTrans_TransIntConst(ENode *expr) { + Object *obj; + UInt8 data[16]; + + CMach_InitIntMem(expr->rtype, expr->data.intval, data); + + obj = CParser_NewGlobalDataObject(NULL); + obj->name = CParser_GetUniqueName(); + obj->type = expr->rtype; + obj->sclass = TK_STATIC; + obj->datatype = DDATA; + CScope_AddGlobalObject(obj); + CInit_DeclareData(obj, data, NULL, obj->type->size); + return create_objectnode(obj); +} + +static ENode *CIRTrans_TransFloatConst(ENode *expr) { + Object *obj; + UInt8 data[16]; + + CMach_InitFloatMem(expr->rtype, expr->data.floatval, data); + + obj = CParser_NewGlobalDataObject(NULL); + obj->name = CParser_GetUniqueName(); + obj->type = expr->rtype; + obj->sclass = TK_STATIC; + obj->datatype = DDATA; + CScope_AddGlobalObject(obj); + CInit_DeclareData(obj, data, NULL, obj->type->size); + return create_objectnode(obj); +} + +static ENode *CIRTrans_TransUnary(ENode *expr, Type *type, StrangeRuntimeFunction *rtfunc) { + if (type->size > 4) { + expr = funccallexpr( + CIRTrans_GetRuntimeFunction(rtfunc, type), + create_objectrefnode(CIRTrans_GetTemporary(type)), + expr, + NULL, + NULL); + expr->flags |= ENODE_FLAG_80; + expr = makemonadicnode(expr, EINDIRECT); + expr->rtype = type; + return expr; + } else { + expr = funccallexpr( + CIRTrans_GetRuntimeFunction(rtfunc, type), + expr, + NULL, + NULL, + NULL); + expr->rtype = type; + return expr; + } +} + +static ENode *CIRTrans_TransBinary(ENode *expr, StrangeRuntimeFunction *rtfunc) { + ENode *expr2; + + if (expr->rtype->size > 4) { + expr2 = funccallexpr( + CIRTrans_GetRuntimeFunction(rtfunc, expr->rtype), + create_objectrefnode(CIRTrans_GetTemporary(expr->rtype)), + expr->data.diadic.left, + expr->data.diadic.right, + NULL); + expr2->flags |= ENODE_FLAG_80; + expr2 = makemonadicnode(expr2, EINDIRECT); + expr2->rtype = expr->rtype; + return expr2; + } else { + expr2 = funccallexpr( + CIRTrans_GetRuntimeFunction(rtfunc, expr->rtype), + expr->data.diadic.left, + expr->data.diadic.right, + NULL, + NULL); + expr2->rtype = expr->rtype; + return expr2; + } +} + +static ENodeList *CIRTrans_TransExprList(ENodeList *list) { + ENodeList *scan; + + for (scan = list; scan; scan = scan->next) + scan->node = CIRTrans_TransExpr(scan->node, 1); + + return list; +} + +static ENode *CIRTrans_TransExpr(ENode *expr, Boolean flag) { + switch (expr->type) { + case EINDIRECT: + case EFORCELOAD: + case EBITFIELD: + expr->data.monadic = CIRTrans_TransExpr(expr->data.monadic, flag); + break; + case EPOSTINC: + expr->data.monadic = CIRTrans_TransExpr(expr->data.monadic, 1); + break; + case EPOSTDEC: + expr->data.monadic = CIRTrans_TransExpr(expr->data.monadic, 1); + break; + case EPREINC: + expr->data.monadic = CIRTrans_TransExpr(expr->data.monadic, 1); + break; + case EPREDEC: + expr->data.monadic = CIRTrans_TransExpr(expr->data.monadic, 1); + break; + case ETYPCON: + expr->data.monadic = CIRTrans_TransExpr(expr->data.monadic, flag); + if (!flag) + return expr->data.monadic; + break; + case EBINNOT: + expr->data.monadic = CIRTrans_TransExpr(expr->data.monadic, flag); + break; + case ELOGNOT: + expr->data.monadic = CIRTrans_TransExpr(expr->data.monadic, flag); + break; + case EMONMIN: + expr->data.monadic = CIRTrans_TransExpr(expr->data.monadic, flag); + break; + case EADD: + expr->data.diadic.left = CIRTrans_TransExpr(expr->data.diadic.left, flag); + expr->data.diadic.right = CIRTrans_TransExpr(expr->data.diadic.right, flag); + break; + case ESUB: + expr->data.diadic.left = CIRTrans_TransExpr(expr->data.diadic.left, flag); + expr->data.diadic.right = CIRTrans_TransExpr(expr->data.diadic.right, flag); + break; + case EMUL: + expr->data.diadic.left = CIRTrans_TransExpr(expr->data.diadic.left, flag); + expr->data.diadic.right = CIRTrans_TransExpr(expr->data.diadic.right, flag); + case EDIV: + expr->data.diadic.left = CIRTrans_TransExpr(expr->data.diadic.left, flag); + expr->data.diadic.right = CIRTrans_TransExpr(expr->data.diadic.right, flag); + break; + case EMODULO: + expr->data.diadic.left = CIRTrans_TransExpr(expr->data.diadic.left, flag); + expr->data.diadic.right = CIRTrans_TransExpr(expr->data.diadic.right, flag); + break; + case ESHL: + expr->data.diadic.left = CIRTrans_TransExpr(expr->data.diadic.left, flag); + expr->data.diadic.right = CIRTrans_TransExpr(expr->data.diadic.right, flag); + break; + case ESHR: + expr->data.diadic.left = CIRTrans_TransExpr(expr->data.diadic.left, flag); + expr->data.diadic.right = CIRTrans_TransExpr(expr->data.diadic.right, flag); + break; + case EROTL: + expr->data.diadic.left = CIRTrans_TransExpr(expr->data.diadic.left, flag); + expr->data.diadic.right = CIRTrans_TransExpr(expr->data.diadic.right, flag); + break; + case EROTR: + expr->data.diadic.left = CIRTrans_TransExpr(expr->data.diadic.left, flag); + expr->data.diadic.right = CIRTrans_TransExpr(expr->data.diadic.right, flag); + break; + case EAND: + expr->data.diadic.left = CIRTrans_TransExpr(expr->data.diadic.left, flag); + expr->data.diadic.right = CIRTrans_TransExpr(expr->data.diadic.right, flag); + break; + case EXOR: + expr->data.diadic.left = CIRTrans_TransExpr(expr->data.diadic.left, flag); + expr->data.diadic.right = CIRTrans_TransExpr(expr->data.diadic.right, flag); + break; + case EOR: + expr->data.diadic.left = CIRTrans_TransExpr(expr->data.diadic.left, flag); + expr->data.diadic.right = CIRTrans_TransExpr(expr->data.diadic.right, flag); + break; + case ELESS: + case EGREATER: + case ELESSEQU: + case EGREATEREQU: + case EEQU: + case ENOTEQU: + expr->data.diadic.left = CIRTrans_TransExpr(expr->data.diadic.left, flag); + expr->data.diadic.right = CIRTrans_TransExpr(expr->data.diadic.right, flag); + if (!flag) { + expr->type = ECOMMA; + expr->rtype = expr->data.diadic.right->rtype; + return expr; + } + break; + case ELAND: + case ELOR: + expr->data.diadic.left = CIRTrans_TransExpr(expr->data.diadic.left, 1); + expr->data.diadic.right = CIRTrans_TransExpr(expr->data.diadic.right, flag); + break; + case EMULV: + case EADDV: + case ESUBV: + case EPMODULO: + case EBCLR: + case EBTST: + case EBSET: + expr->data.diadic.left = CIRTrans_TransExpr(expr->data.diadic.left, flag); + expr->data.diadic.right = CIRTrans_TransExpr(expr->data.diadic.right, flag); + break; + case EASS: + expr->data.diadic.left = CIRTrans_TransExpr(expr->data.diadic.left, 1); + expr->data.diadic.right = CIRTrans_TransExpr(expr->data.diadic.right, 1); + break; + case EMULASS: + case EDIVASS: + case EADDASS: + case ESUBASS: + expr->data.diadic.left = CIRTrans_TransExpr(expr->data.diadic.left, 1); + expr->data.diadic.right = CIRTrans_TransExpr(expr->data.diadic.right, 1); + break; + case EMODASS: + case ESHLASS: + case ESHRASS: + case EANDASS: + case EXORASS: + case EORASS: + expr->data.diadic.left = CIRTrans_TransExpr(expr->data.diadic.left, 1); + expr->data.diadic.right = CIRTrans_TransExpr(expr->data.diadic.right, 1); + break; + case ECOMMA: + expr->data.diadic.left = CIRTrans_TransExpr(expr->data.diadic.left, 0); + expr->data.diadic.right = CIRTrans_TransExpr(expr->data.diadic.right, flag); + break; + case ECOND: + expr->data.cond.cond = CIRTrans_TransExpr(expr->data.cond.cond, 1); + expr->data.cond.expr1 = CIRTrans_TransExpr(expr->data.cond.expr1, 1); + expr->data.cond.expr2 = CIRTrans_TransExpr(expr->data.cond.expr2, 1); + break; + case EMFPOINTER: + expr->data.mfpointer.accessnode = CIRTrans_TransExpr(expr->data.mfpointer.accessnode, flag); + expr->data.mfpointer.mfpointer = CIRTrans_TransExpr(expr->data.mfpointer.mfpointer, flag); + break; + case EFUNCCALL: + case EFUNCCALLP: + if ( + ENODE_IS(expr->data.funccall.funcref, EOBJREF) && + !strcmp(expr->data.funccall.funcref->data.objref->name->name, "__alloca") + ) + alloca_called = 1; + expr->data.funccall.funcref = CIRTrans_TransExpr(expr->data.funccall.funcref, 1); + expr->data.funccall.args = CIRTrans_TransExprList(expr->data.funccall.args); + break; + case ENULLCHECK: + expr->data.nullcheck.nullcheckexpr = CIRTrans_TransExpr(expr->data.nullcheck.nullcheckexpr, 1); + expr->data.nullcheck.condexpr = CIRTrans_TransExpr(expr->data.nullcheck.condexpr, 1); + break; + case ENEWEXCEPTION: + case ENEWEXCEPTIONARRAY: + expr->data.newexception.initexpr = CIRTrans_TransExpr(expr->data.newexception.initexpr, 1); + expr->data.newexception.tryexpr = CIRTrans_TransExpr(expr->data.newexception.tryexpr, 1); + break; + case EINITTRYCATCH: + expr->data.itc.initexpr = CIRTrans_TransExpr(expr->data.itc.initexpr, 1); + expr->data.itc.tryexpr = CIRTrans_TransExpr(expr->data.itc.tryexpr, 1); + expr->data.itc.catchexpr = CIRTrans_TransExpr(expr->data.itc.catchexpr, 1); + expr->data.itc.result = CIRTrans_TransExpr(expr->data.itc.result, 1); + break; + case EINTCONST: + case EFLOATCONST: + case ESTRINGCONST: + case EOBJREF: + case EPRECOMP: + case ETEMP: + case ELABEL: + case EMEMBER: + case EINSTRUCTION: + case EVECTOR128CONST: + break; + default: + CError_FATAL(1947); + } + + return expr; +} + +void CIRTrans_Transform(void) { + cirtrans_temps = NULL; +} |