static EXPRESSION *newReturn(TYPE *tp) { EXPRESSION *exp ; if (!isstructured(tp) && !isvoid(tp)) { exp = varNode(en_auto, anonymousVar(sc_auto, tp)); deref(tp, &exp); } else exp = intNode(en_c_i, 0); return exp; }
static STATEMENT *SetupArguments(FUNCTIONCALL *params) { STATEMENT *st = NULL, **stp = &st; ARGLIST *al = params->arguments; HASHREC *hr = params->sp->inlineFunc.syms->table[0]; while (al && hr) { SYMBOL *sx; if (al == params->arguments && (params->sp->storage_class == sc_member || params->sp->storage_class == sc_virtual)) { LIST *l = Alloc(sizeof(LIST)); l->next = thisptrs; thisptrs = l; l->data = (void *)(sx = makeID(sc_auto, &stdpointer, NULL, "__$this$__")); } else { sx = (SYMBOL *)hr->p; } if (!sx->altered && !sx->addressTaken && !sideEffects(al->exp)) { // well if the expression is too complicated it gets evaluated over and over // but maybe the backend can clean it up again... sx->inlineFunc.stmt = (STATEMENT *)al->exp; } else { EXPRESSION *tnode = varNode(en_auto, anonymousVar(sc_auto, sx->tp)); deref(sx->tp, &tnode); sx->inlineFunc.stmt = (STATEMENT *)tnode; tnode = exprNode(en_assign, tnode, al->exp); *stp = Alloc(sizeof(STATEMENT)); memset(*stp, 0 , sizeof(STATEMENT)); (*stp)->type = st_expr; (*stp)->select = tnode; stp = &(*stp)->next; } al = al->next; if (hr) hr = hr->next; } return st; }
void SetupVariables(SYMBOL *sp) /* Copy all the func args into the xsyms table. * This copies the function parameters twice... */ { HASHTABLE *syms = sp->inlineFunc.syms; while (syms) { HASHREC *hr = syms->table[0]; while (hr) { SYMBOL *sx = (SYMBOL *)hr->p; if (sx->storage_class == sc_auto) { SYMBOL *sxnew = anonymousVar(sc_auto, sx->tp); EXPRESSION *ev = varNode(en_auto, sxnew); deref(sx->tp, &ev); sx->inlineFunc.stmt = (STATEMENT *)ev; } hr = hr->next; } syms = syms->next; } }
void genfunc(SYMBOL *funcsp) /* * generate a function body and dump the icode */ { IMODE *allocaAP = NULL; SYMBOL *oldCurrentFunc; EXPRESSION *funcexp = varNode(en_global, funcsp); if (total_errors) return; // //printf("%s\n", funcsp->name); contlab = breaklab = - 1; structret_imode = 0 ; tempCount = 0; blockCount = 0; blockMax = 0; exitBlock = 0; oldCurrentFunc = theCurrentFunc; theCurrentFunc = funcsp; iexpr_func_init(); /* firstlabel = nextLabel;*/ cseg(); gen_line(funcsp->linedata); gen_func(funcexp, 1); /* in C99 inlines can clash if declared 'extern' in multiple modules */ /* in C++ we introduce virtual functions that get coalesced at link time */ if (cparams.prm_cplusplus && funcsp->linkage == lk_inline) gen_virtual(funcsp, FALSE); else { if (funcsp->storage_class == sc_global) globaldef(funcsp); else localdef(funcsp); gen_strlab(funcsp); /* name of function */ } addblock( - 1); if (funcsp->linkage == lk_interrupt || funcsp->linkage == lk_fault) { gen_icode(i_pushcontext, 0,0,0); /* if (funcsp->loadds) */ /* gen_icode(i_loadcontext, 0,0,0); */ } gen_icode(i_prologue,0,0,0); gen_label(startlab); /* if (funcsp->loadds && funcsp->farproc) */ /* gen_icode(i_loadcontext, 0,0,0); */ AllocateLocalContext(NULL, funcsp); if (funcsp->allocaUsed) { EXPRESSION *allocaExp = varNode(en_auto, anonymousVar(sc_auto, &stdpointer)); allocaAP = gen_expr(funcsp, allocaExp, 0, ISZ_ADDR); gen_icode(i_savestack, 0, allocaAP, 0); } /* Generate the icode */ /* LCSE is done while code is generated */ genstmt(funcsp->inlineFunc.stmt->lower, funcsp); if (funcsp->inlineFunc.stmt->blockTail) { gen_icode(i_functailstart, 0, 0, 0); genstmt(funcsp->inlineFunc.stmt->blockTail, funcsp); gen_icode(i_functailend, 0, 0, 0); } genreturn(0, funcsp, 1, 0, allocaAP); gen_func(funcexp, 0); tFree(); InsertParameterThunks(funcsp, blockArray[1]); optimize(funcsp); FreeLocalContext(NULL, funcsp); AllocateStackSpace(funcsp); FillInPrologue(intermed_head, funcsp); /* Code gen from icode */ rewrite_icode(); /* Translate to machine code & dump */ if (chosenAssembler->gen->post_function_gen) chosenAssembler->gen->post_function_gen(funcsp, intermed_head); if (cparams.prm_cplusplus && funcsp->linkage == lk_inline) gen_endvirtual(funcsp); intermed_head = NULL; dag_rundown(); oFree(); theCurrentFunc = oldCurrentFunc; if (blockCount > maxBlocks) maxBlocks = blockCount; if (tempCount > maxTemps) maxTemps = tempCount; }
void genreturn(STATEMENT *stmt, SYMBOL *funcsp, int flag, int noepilogue, IMODE *allocaAP) /* * generate a return statement. */ { IMODE *ap, *ap1, *ap3; EXPRESSION ep; /* returns a value? */ if (stmt != 0 && stmt->select != 0) { if (basetype(funcsp->tp)->btp && (isstructured(basetype(funcsp->tp)->btp) || basetype(basetype(funcsp->tp)->btp)->type == bt_memberptr)) { SYMBOL *sp = anonymousVar(sc_parameter, &stdpointer); EXPRESSION *en = varNode(en_auto, sp); IMODE *ap3 = gen_expr(funcsp, stmt->select, 0, ISZ_ADDR), *ap2, *ap1; DumpIncDec(funcsp); if (!ap3->retval) { ap1 = LookupLoadTemp(NULL, ap3); if (ap1 != ap3) { IMODE *barrier; if (stmt->select->isatomic) { barrier = doatomicFence(funcsp, stmt->select, NULL); } gen_icode(i_assn, ap1, ap3, NULL); if (stmt->select->isatomic) { doatomicFence(funcsp, stmt->select, barrier); } } } else { ap1 = ap3; } if ((funcsp->linkage == lk_pascal) && basetype(funcsp->tp)->syms->table[0] && ((SYMBOL *)basetype(funcsp->tp)->syms->table[0])->tp->type != bt_void) { sp->offset = funcsp->paramsize; } else { sp->offset = chosenAssembler->arch->retblocksize+(funcsp->farproc *getSize(bt_pointer)); if (funcsp->storage_class == sc_member || funcsp->storage_class == sc_virtual) sp->offset += getSize(bt_pointer); } en = exprNode(en_l_p, en, NULL); ap3 = gen_expr(funcsp, en, 0, ISZ_ADDR); ap = LookupLoadTemp(NULL, ap3); if (ap != ap3) { IMODE *barrier; if (en->isatomic) { barrier = doatomicFence(funcsp, en, NULL); } gen_icode(i_assn, ap, ap3, NULL); if (en->isatomic) { doatomicFence(funcsp, en, barrier); } } gen_icode(i_assnblock, make_immed(ISZ_NONE, basetype(funcsp->tp)->btp->size), ap, ap1); ap1 = tempreg(ISZ_ADDR, 0); ap1->retval = TRUE; gen_icode(i_assn, ap1, ap, NULL); } else if (basetype(funcsp->tp)->btp && basetype(funcsp->tp)->btp->type == bt_memberptr) { ap3 = gen_expr(funcsp, stmt->select, F_VOL, ISZ_ADDR); DumpIncDec(funcsp); ap = LookupLoadTemp(NULL, ap3); if (ap != ap3) { IMODE *barrier; if (stmt->select->isatomic) { barrier = doatomicFence(funcsp, stmt->select, NULL); } gen_icode(i_assn, ap, ap3, NULL); if (stmt->select->isatomic) { doatomicFence(funcsp, stmt->select, barrier); } } ap1 = tempreg(ISZ_ADDR, 0); ap1->retval = TRUE; gen_icode(i_assn, ap1, ap, 0); } else { int size = natural_size(stmt->select); ap3 = gen_expr(funcsp, stmt->select, 0, size); DumpIncDec(funcsp); ap = LookupLoadTemp(NULL, ap3); if (ap != ap3) { IMODE *barrier; if (stmt->select->isatomic) { barrier = doatomicFence(funcsp, stmt->select, NULL); } gen_icode(i_assn, ap, ap3, NULL); if (stmt->select->isatomic) { doatomicFence(funcsp, stmt->select, barrier); } } if (abs(size) < ISZ_UINT) size = -ISZ_UINT; ap1 = tempreg(size, 0); ap1->retval = TRUE; gen_icode(i_assn, ap1, ap, 0); } } else { DumpIncDec(funcsp); } /* create the return or a branch to the return * return is put at end of function... */ if (flag) { int retsize = 0; if (funcsp->linkage == lk_pascal || funcsp->linkage == lk_stdcall) { retsize = funcsp->paramsize ; } gen_label(retlab); if (!noepilogue) { if (allocaAP) { gen_icode(i_loadstack, 0, allocaAP, 0); } /* if (funcsp->loadds && funcsp->farproc) gen_icode(i_unloadcontext,0,0,0); */ gen_icode(i_epilogue,0,0,0); if (funcsp->linkage == lk_interrupt || funcsp->linkage == lk_fault) { /* if (funcsp->loadds) gen_icode(i_unloadcontext,0,0,0); */ gen_icode(i_popcontext, 0,0,0); gen_icode(i_rett, 0, make_immed(ISZ_NONE,funcsp->linkage == lk_interrupt), 0); } else { gen_icode(i_ret, 0, make_immed(ISZ_NONE,retsize), 0); } } } else { /* not using gen_igoto because it will make a new block */ gen_icode(i_goto, NULL, NULL, NULL); intermed_tail->dc.v.label = retlab; } }
EXPRESSION *convertInitToExpression(TYPE *tp, SYMBOL *sp, SYMBOL *funcsp, INITIALIZER *init, EXPRESSION *thisptr, BOOLEAN isdest) { EXPRESSION *rv = NULL, **pos = &rv; EXPRESSION *exp = NULL, **expp; EXPRESSION *expsym; BOOLEAN noClear = FALSE; if (sp) sp->destructed = FALSE; if (isstructured(tp) || isarray(tp)) { INITIALIZER **i2 = &init; while (*i2) i2 = &(*i2)->next; initInsert(i2, NULL, NULL, tp->size, FALSE); } if (!sp) { if (thisptr) expsym = thisptr; else if (funcsp) { SYMBOL *sp = (SYMBOL *)basetype(funcsp->tp)->syms->table[0] ? (SYMBOL *)basetype(funcsp->tp)->syms->table[0]->p : NULL; if (sp && sp->thisPtr) expsym = varNode(en_auto, sp ); // this ptr else expsym = anonymousVar(sc_auto, tp); } else { expsym = intNode(en_c_i, 0); diag("convertInitToExpression: no this ptr"); } } else switch (sp->storage_class) { case sc_auto: case sc_register: case sc_parameter: expsym = varNode(en_auto, sp); break; case sc_localstatic: if (sp->linkage3 == lk_threadlocal) { expsym = exprNode(en_add, thisptr, intNode(en_c_i, sp->offset)); } else { expsym = varNode(en_label, sp); } break; case sc_static: case sc_global: if (sp->linkage3 == lk_threadlocal) { expsym = exprNode(en_add, thisptr, intNode(en_c_i, sp->offset)); } else { expsym = varNode(en_global, sp); } break; case sc_member: case sc_mutable: if (thisptr) expsym = thisptr; else if (funcsp) expsym = varNode(en_auto, (SYMBOL *)basetype(funcsp->tp)->syms->table[0]->p); // this ptr else { expsym = intNode(en_c_i, 0); diag("convertInitToExpression: no this ptr"); } expsym = exprNode(en_add, expsym, intNode(en_c_i, sp->offset)); break; case sc_external: /* expsym = varNode(en_global, sp); break; */ default: diag("convertInitToExpression: unknown sym type"); expsym = intNode(en_c_i, 0); break; } while (init) { exp = NULL; if (init->basetp) { if (init->noassign) { exp = init->exp; if (exp->type == en_thisref) exp = exp->left; if (thisptr && exp->type == en_func) { EXPRESSION *exp1 = init->offset ? exprNode(en_add, expsym, intNode(en_c_i, init->offset)) : expsym; if (isarray(tp)) { exp->v.func->arguments->exp = exp1; } else { exp->v.func->thisptr = exp1; } } exp = init->exp; } else if (!init->exp) { // usually empty braces, coudl be an error though exp = exprNode(en_blockclear, expsym, NULL); exp->size = init->offset; } else if (isstructured(init->basetp) || isarray(init->basetp)) { INITIALIZER *temp = init; if (isstructured(temp->basetp)) { EXPRESSION *exp2 = init->exp; while(exp2->type == en_not_lvalue) exp2 = exp2->left; if (exp2->type == en_func && exp2->v.func->returnSP) { exp2->v.func->returnSP->allocate = FALSE; exp2->v.func->returnEXP = expsym; exp = exp2; noClear = TRUE; } else if (exp2->type == en_thisref && exp2->left->v.func->returnSP) { exp2->left->v.func->returnSP->allocate = FALSE; exp2->left->v.func->returnEXP = expsym; exp = exp2; noClear = TRUE; } else if (cparams.prm_cplusplus) { TYPE *ctype = init->basetp; FUNCTIONCALL *funcparams = Alloc(sizeof(FUNCTIONCALL)); funcparams->arguments = Alloc(sizeof(INITLIST)); funcparams->arguments->tp = ctype; funcparams->arguments->exp = exp2; callConstructor(&ctype, &expsym, funcparams, FALSE, NULL, TRUE, FALSE, FALSE, FALSE, FALSE); exp = expsym; } else { exp = exprNode(en_blockassign, expsym, exp2); exp->size = init->basetp->size; } } else { TYPE *btp = init->basetp; while(isarray(btp)) btp = basetype(btp)->btp; btp = basetype(btp); while (temp) { if (temp->exp) if (!isarithmeticconst(temp->exp) && !isconstaddress(temp->exp)) break; temp = temp->next; } if (temp) { /* some members are non-constant expressions */ if (!cparams.prm_c99 && !cparams.prm_cplusplus) error(ERR_C99_NON_CONSTANT_INITIALIZATION); if (!sp) { expsym = anonymousVar(sc_auto, init->basetp); sp = expsym->v.sp; } if (!isstructured(btp) || btp->sp->trivialCons) { exp = exprNode(en_blockclear, expsym, NULL); exp->size = init->basetp->size; exp = exprNode(en_void, exp, NULL); expp = &exp->right; } else { expp = &exp; } { EXPRESSION *right = init->exp; if (!isstructured(btp)) { EXPRESSION *asn = exprNode(en_add, expsym, intNode(en_c_i, init->offset)); deref(init->basetp, &asn); cast(init->basetp, &right); right = exprNode(en_assign, asn, right); } if (*expp) *expp = exprNode(en_void, *expp, right); else *expp = right; expp = &(*expp)->right; } } else { /* constant expression */ SYMBOL *spc ; IncGlobalFlag(); exp = anonymousVar(sc_localstatic, init->basetp); spc = exp->v.sp; spc->init = init ; insertInitSym(spc); insert(spc, localNameSpace->syms); DecGlobalFlag(); spc->label =nextLabel++; if (expsym) { if (cparams.prm_cplusplus && isstructured(init->basetp) && !init->basetp->sp->trivialCons) { TYPE *ctype = init->basetp; FUNCTIONCALL *funcparams = Alloc(sizeof(FUNCTIONCALL)); funcparams->arguments = Alloc(sizeof(INITLIST)); funcparams->arguments->tp = ctype; funcparams->arguments->exp = exp; callConstructor(&ctype, &expsym, funcparams, FALSE, NULL, TRUE, FALSE, FALSE, FALSE, FALSE); exp = expsym; } else { exp = exprNode(en_blockassign, expsym, exp); exp->size = init->basetp->size; } } } } } else if (basetype(init->basetp)->type == bt_memberptr) { EXPRESSION *exp2 = init->exp;; while(exp2->type == en_not_lvalue) exp2 = exp2->left; if (exp2->type == en_func && exp2->v.func->returnSP) { exp2->v.func->returnSP->allocate = FALSE; exp2->v.func->returnEXP = expsym; exp = exp2; } else { if (exp2->type == en_memberptr) { int lab = dumpMemberPtr(exp2->v.sp, init->basetp, TRUE); exp2 = intNode(en_labcon, lab); } exp = exprNode(en_blockassign, expsym, exp2); exp->size = init->basetp->size; } } else { EXPRESSION *exps = expsym; if (init->offset) exps = exprNode(en_add, exps, intNode(en_c_i, init->offset)); deref(init->basetp, &exps); exp = init->exp; if (exp->type == en_void) { cast(init->basetp, &exp->right); if (expsym) exp->right = exprNode(en_assign, exps, exp->right); } else { cast(init->basetp, &exp); if (exps) exp = exprNode(en_assign, exps, exp); } } if (sp && sp->init && isatomic(init->basetp) && needsAtomicLockFromType(init->basetp)) { EXPRESSION *p1 = exprNode(en_add, expsym->left, intNode(en_c_i, init->basetp->size - ATOMIC_FLAG_SPACE)); deref(&stdint, &p1); p1 = exprNode(en_assign, p1, intNode(en_c_i, 0)); exp = exprNode(en_void, exp, p1); } } if (exp) { if (*pos) { *pos = exprNode(en_void, *pos, exp); pos = &(*pos)->right; } else { *pos = exp; } } init = init->next; } if (sp && sp->storage_class == sc_localstatic) { if (isdest) { rv = exprNode(en_voidnz, exprNode(en_void, sp->localInitGuard, rv), intNode(en_c_i, 0)); } else { EXPRESSION *guard = anonymousVar(sc_static, &stdint); insertInitSym(guard->v.sp); deref(&stdpointer, &guard); optimize_for_constants(&rv); rv = exprNode(en_voidnz, exprNode(en_void, exprNode(en_not, guard, NULL), exprNode(en_void, rv, exprNode(en_autoinc, guard, intNode(en_c_i, 1)))), intNode(en_c_i, 0)); sp->localInitGuard = guard; } } // plop in a clear block if necessary if (sp && !noClear && !isdest && (isarray(tp) || isstructured(tp) && (!cparams.prm_cplusplus || basetype(tp)->sp->trivialCons))) { EXPRESSION *fexp = expsym; EXPRESSION *exp; if (fexp->type == en_thisref) fexp = fexp->left->v.func->thisptr; exp = exprNode(en_blockclear, fexp, NULL); exp->size = sp->tp->size; rv = exprNode(en_void, exp, rv); } if (isstructured(tp) && !cparams.prm_cplusplus) { if (*pos) { *pos = exprNode(en_void, *pos, expsym); pos = &(*pos)->right; } else { *pos = expsym; } } return rv; }
void genreturn(STATEMENT *stmt, SYMBOL *funcsp, int flag, int noepilogue, IMODE *allocaAP) /* * generate a return statement. */ { IMODE *ap = NULL, *ap1, *ap3; EXPRESSION ep; int size; /* returns a value? */ if (stmt != 0 && stmt->select != 0) { if (basetype(funcsp->tp)->btp && (isstructured(basetype(funcsp->tp)->btp) || basetype(basetype(funcsp->tp)->btp)->type == bt_memberptr)) { EXPRESSION *en = anonymousVar(sc_parameter, &stdpointer); SYMBOL *sp = en->v.sp; gen_expr(funcsp, stmt->select, 0, ISZ_ADDR); DumpIncDec(funcsp); sp->offset = chosenAssembler->arch->retblocksize; sp->allocate = FALSE; if ((funcsp->linkage == lk_pascal) && basetype(funcsp->tp)->syms->table[0] && ((SYMBOL *)basetype(funcsp->tp)->syms->table[0])->tp->type != bt_void) sp->offset = funcsp->paramsize; deref(&stdpointer, &en); ap = gen_expr(funcsp, en, 0, ISZ_ADDR); size = ISZ_ADDR; } else { size = natural_size(stmt->select); ap3 = gen_expr(funcsp, stmt->select, 0, size); DumpIncDec(funcsp); ap = LookupLoadTemp(NULL, ap3); if (ap != ap3) { IMODE *barrier; if (stmt->select->isatomic) { barrier = doatomicFence(funcsp, stmt->select, NULL); } gen_icode(i_assn, ap, ap3, NULL); if (stmt->select->isatomic) { doatomicFence(funcsp, stmt->select, barrier); } } if (abs(size) < ISZ_UINT) size = -ISZ_UINT; } } else { DumpIncDec(funcsp); } if (ap) { ap1 = tempreg(size, 0); ap1->retval = TRUE; gen_icode(i_assn, ap1, ap, 0); } if (stmt && stmt->destexp) { gen_expr(funcsp, stmt->destexp, F_NOVALUE, ISZ_ADDR); } /* create the return or a branch to the return * return is put at end of function... */ if (flag) { int retsize = 0; if (funcsp->linkage == lk_pascal || funcsp->linkage == lk_stdcall) { retsize = funcsp->paramsize ; } gen_label(retlab); if (!noepilogue) { if (allocaAP) { gen_icode(i_loadstack, 0, allocaAP, 0); } /* if (funcsp->loadds && funcsp->farproc) gen_icode(i_unloadcontext,0,0,0); */ if (cparams.prm_xcept && funcsp->xc && funcsp->xc->xcRundownFunc) gen_expr(funcsp, funcsp->xc->xcRundownFunc, F_NOVALUE, ISZ_UINT); gen_icode(i_epilogue,0,0,0); if (funcsp->linkage == lk_interrupt || funcsp->linkage == lk_fault) { /* if (funcsp->loadds) gen_icode(i_unloadcontext,0,0,0); */ gen_icode(i_popcontext, 0,0,0); gen_icode(i_rett, 0, make_immed(ISZ_UINT,funcsp->linkage == lk_interrupt), 0); } else { gen_icode(i_ret, 0, make_immed(ISZ_UINT,retsize), 0); } } } else { /* not using gen_igoto because it will make a new block */ gen_icode(i_goto, NULL, NULL, NULL); intermed_tail->dc.v.label = retlab; } }