EXPRESSION *doinline(FUNCTIONCALL *params, SYMBOL *funcsp) { static SYMBOL *curfunc; STATEMENT *stmt = NULL, **stp = &stmt; EXPRESSION *newExpression; BOOL allocated = FALSE; if (funcsp) curfunc = funcsp; if (!isfunction(params->functp)) return NULL; if (params->sp->linkage != lk_inline) return NULL; if (!params->sp->inlineFunc.syms) return NULL; if (!localNameSpace->syms) { allocated = TRUE; AllocateLocalContext(NULL, NULL); } stmt = SetupArguments(params); SetupVariables(params->sp); while (*stp) stp = &(*stp)->next; *stp = inlinestmt(params->sp->inlineFunc.stmt); newExpression = exprNode(en_stmt, NULL, NULL); newExpression->v.stmt = stmt; if (params->sp->retcount == 1) { /* optimization for simple inline functions that only have * one return statement, don't save to an intermediate variable */ newExpression->left = scanReturn(stmt, basetype(params->sp->tp)->btp); } else { newExpression->left = newReturn(basetype(params->sp->tp)->btp); reduceReturns(stmt, params->sp->tp->btp, newExpression->left); } if (params->sp->storage_class == sc_virtual || params->sp->storage_class == sc_member) thisptrs = thisptrs->next; if (allocated) { FreeLocalContext(NULL, NULL); } if (funcsp) curfunc = NULL; return newExpression; }
IMODE *imake_label(int label) /* * make a node to reference an immediate value i. */ { IMODE *ap = (IMODE *)Alloc(sizeof(IMODE)); ap->mode = i_immed; ap->offset = exprNode(en_labcon, NULL, NULL); ap->offset->v.i = label; ap->size = ISZ_ADDR; return ap; }
static void inlineResetReturn(STATEMENT *block, TYPE *rettp, EXPRESSION *retnode) { EXPRESSION *exp; if (isstructured(rettp)) { diag("structure in inlineResetReturn"); } else { exp = block->select; cast(rettp, &exp); exp = exprNode(en_assign, retnode, exp); } block->type = st_expr; block->select = 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 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; } }
static EXPRESSION *createLambda(BOOLEAN noinline) { EXPRESSION *rv = NULL, **cur = &rv; HASHREC *hr; EXPRESSION *clsThs, *parentThs; SYMBOL *cls = makeID(lambdas->enclosingFunc ? sc_auto : sc_localstatic, lambdas->cls->tp, NULL, AnonymousName()); SetLinkerNames(cls, lk_cdecl); cls->allocate = TRUE; if (lambdas->enclosingFunc) { insert(cls, localNameSpace->syms); clsThs = varNode(en_auto, cls); // this ptr } else { insert(cls, globalNameSpace->syms); // well if we could put this as an auto in the init func that would be good but there is no way to do that here... clsThs = varNode(en_label, cls); // this ptr cls->label = nextLabel++; insertInitSym(cls); } { INITIALIZER *init = NULL; EXPRESSION *exp = clsThs; callDestructor(cls, NULL, &exp, NULL, TRUE, FALSE, FALSE); initInsert(&init, cls->tp, exp, 0, TRUE); if (cls->storage_class != sc_auto) { insertDynamicDestructor(cls, init); } else { cls->dest = init; } } parentThs = varNode(en_auto, (SYMBOL *)basetype(lambdas->func->tp)->syms->table[0]->p); // this ptr hr = lambdas->cls->tp->syms->table[0]; while (hr) { SYMBOL *sp = (SYMBOL *)hr->p; EXPRESSION *en = NULL, *en1 = NULL; if (!strcmp(sp->name, "$self")) { en1 = clsThs; en = varNode(en_label, sp); deref(&stdpointer, &en); en = exprNode(en_assign, en, en1); } else if (!strcmp(sp->name, "$parent")) { en1 = parentThs; // get parent from function call deref(&stdpointer, &en1); en = exprNode(en_add, clsThs, intNode(en_c_i, sp->offset)) ; deref(&stdpointer, &en); en = exprNode(en_assign, en, en1); } else if (!strcmp(sp->name, "$this")) { if (!lambdas->next || !lambdas->captureThis) { en1 = parentThs; // get parent from function call } else { SYMBOL *parent = search("$parent", lambdas->cls->tp->syms); en1 = varNode(en_auto, cls); deref(&stdpointer, &en1); en1 = exprNode(en_add, en1, intNode(en_c_i, parent->offset)); } deref(&stdpointer, &en1); en = exprNode(en_add, clsThs, intNode(en_c_i, sp->offset)) ; deref(&stdpointer, &en); en = exprNode(en_assign, en, en1); } else if (sp->lambdaMode) { LAMBDASP *lsp = (LAMBDASP *)search(sp->name, lambdas->captured); if (lsp) { en1 = exprNode(en_add, clsThs, intNode(en_c_i, sp->offset)); if (sp->lambdaMode == cmRef) { SYMBOL *capture = lsp->parent; deref(&stdpointer, &en1); if (capture->lambdaMode) { en = parentThs; deref(&stdpointer, &en); en = exprNode(en_add, en, intNode(en_c_i, capture->offset)); } else // must be an sc_auto { en = varNode(en_auto, capture); } if (isref(capture->tp)) { deref(&stdpointer, &en); } en = exprNode(en_assign, en1, en); } else // cmValue { SYMBOL *capture = lsp->parent; TYPE *ctp = capture->tp; if (capture->lambdaMode) { en = parentThs; deref(&stdpointer, &en); en = exprNode(en_add, en, intNode(en_c_i, capture->offset)); } else // must be an sc_auto { en = varNode(en_auto, capture); } if (isref(ctp)) { ctp = basetype(ctp)->btp; deref(&stdpointer, &en); } if (isstructured(ctp)) { FUNCTIONCALL *params = (FUNCTIONCALL *)Alloc(sizeof(FUNCTIONCALL)); params->arguments = (INITLIST *)Alloc(sizeof(INITLIST)); params->arguments->tp = ctp; params->arguments->exp = en; if (!callConstructor(&ctp, &en1, params, FALSE, NULL, TRUE, FALSE, TRUE, FALSE, FALSE)) errorsym(ERR_NO_APPROPRIATE_CONSTRUCTOR, lsp->sym); en = en1; } else { deref(ctp, &en1); deref(ctp, &en); en = exprNode(en_assign, en1, en); } } } else { diag("createLambda: no capture var"); } } if (en) { *cur = exprNode(en_void, en, NULL); cur = &(*cur)->right; } hr = hr->next; } *cur = clsThs; // this expression will be used in copy constructors, or discarded if unneeded return rv; }
void cast(TYPE *tp, EXPRESSION **exp) { enum e_node en = en_x_i; tp = basetype(tp); switch (tp->type == bt_enum ? tp->btp->type : tp->type) { case bt_lref: case bt_rref: en = en_x_p; break; case bt_func: case bt_ifunc: en = en_x_p; break; case bt_bit: en = en_x_bit; break; case bt_bool: en = en_x_bool; break; case bt_char: if (cparams.prm_charisunsigned) en = en_x_uc; else en = en_x_c; break; case bt_signed_char: en = en_x_c; break; case bt_unsigned_char: en = en_x_uc; break; case bt_char16_t: en = en_x_u16; break; case bt_char32_t: en = en_x_u32; break; case bt_short: en = en_x_s; break; case bt_unsigned_short: en = en_x_us; break; case bt_wchar_t: en = en_x_wc; break; case bt_int: en = en_x_i; break; case bt_unsigned: en = en_x_ui; break; case bt_long: en = en_x_l; break; case bt_unsigned_long: en = en_x_ul; break; case bt_long_long: en = en_x_ll; break; case bt_unsigned_long_long: en = en_x_ull; break; case bt_float: en = en_x_f; break; case bt_double: en = en_x_d; break; case bt_long_double: en = en_x_ld; break; case bt_float_complex: en = en_x_fc; break; case bt_double_complex: en = en_x_dc; break; case bt_long_double_complex: en = en_x_ldc; break; case bt_float_imaginary: en = en_x_fi; break; case bt_double_imaginary: en = en_x_di; break; case bt_long_double_imaginary: en = en_x_ldi; break; case bt_pointer: case bt_aggregate: en = en_x_p; break; case bt_void: return; case bt_templateparam: case bt_templateselector: case bt_templatedecltype: break; default: diag("cast error"); break; } *exp = exprNode(en, *exp, NULL); }
void deref(TYPE *tp, EXPRESSION **exp) { enum e_node en = en_l_i; tp = basetype(tp); switch ((tp->type == bt_enum && tp->btp ) ? tp->btp->type : tp->type) { case bt_lref: /* only used during initialization */ en = en_l_ref; break; case bt_rref: /* only used during initialization */ en = en_l_ref; break; case bt_bit: en = en_l_bit; break; case bt_bool: en = en_l_bool; break; case bt_char: if (cparams.prm_charisunsigned) en = en_l_uc; else en = en_l_c; break; case bt_signed_char: en = en_l_c; break; case bt_char16_t: en = en_l_u16; break; case bt_char32_t: en = en_l_u32; break; case bt_unsigned_char: en = en_l_uc; break; case bt_short: en = en_l_s; break; case bt_unsigned_short: en = en_l_us; break; case bt_wchar_t: en = en_l_wc; break; case bt_int: en = en_l_i; break; case bt_unsigned: en = en_l_ui; break; case bt_long: en = en_l_l; break; case bt_unsigned_long: en = en_l_ul; break; case bt_long_long: en = en_l_ll; break; case bt_unsigned_long_long: en = en_l_ull; break; case bt_float: en = en_l_f; break; case bt_double: en = en_l_d; break; case bt_long_double: en = en_l_ld; break; case bt_float_complex: en = en_l_fc; break; case bt_double_complex: en = en_l_dc; break; case bt_long_double_complex: en = en_l_ldc; break; case bt_float_imaginary: en = en_l_fi; break; case bt_double_imaginary: en = en_l_di; break; case bt_long_double_imaginary: en = en_l_ldi; break; case bt_pointer: if (tp->array || tp->vla) return; en = en_l_p; break; case bt_struct: case bt_class: case bt_union: case bt_func: case bt_ifunc: case bt_any: case bt_templateparam: case bt_templateselector: case bt_templatedecltype: case bt_memberptr: case bt_aggregate: return; default: diag("deref error"); break; } *exp = exprNode(en, *exp, NULL); }
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 genfunc(SYMBOL *funcsp) /* * generate a function body and dump the icode */ { IMODE *allocaAP = NULL; SYMBOL *oldCurrentFunc; EXPRESSION *funcexp = varNode(en_global, funcsp); SYMBOL *tmpl = funcsp; if (total_errors) return; while (tmpl) if (tmpl->templateLevel) break; else tmpl = tmpl->parentClass; // //printf("%s\n", funcsp->name); temporarySymbols = NULL; contlab = breaklab = - 1; structret_imode = 0 ; tempCount = 0; blockCount = 0; blockMax = 0; exitBlock = 0; consIndex = 0; oldCurrentFunc = theCurrentFunc; theCurrentFunc = funcsp; iexpr_func_init(); if (funcsp->xc && funcsp->xc->xctab) { EXPRESSION *exp; xcexp = varNode(en_auto, funcsp->xc->xctab); xcexp = exprNode(en_add, xcexp, intNode(en_c_i, (LLONG_TYPE)&(((struct _xctab *)0)->funcIndex))); deref(&stdpointer, &xcexp); exp = intNode(en_c_i, 0); xcexp = exprNode(en_assign, xcexp, exp); } else { xcexp = NULL; } /* 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 || tmpl)) gen_virtual(funcsp, FALSE); else { if (funcsp->storage_class == sc_global || (funcsp->storage_class == sc_member || funcsp->storage_class == sc_virtual) && funcsp->inlineFunc.stmt) 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 (cparams.prm_xcept && funcsp->xc && funcsp->xc->xcInitializeFunc) { gen_expr(funcsp, funcsp->xc->xcInitializeFunc, F_NOVALUE, ISZ_UINT); gen_label(funcsp->xc->xcInitLab); } /* if (funcsp->loadds && funcsp->farproc) */ /* gen_icode(i_loadcontext, 0,0,0); */ AllocateLocalContext(NULL, funcsp); if (funcsp->allocaUsed) { EXPRESSION *allocaExp = 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 || tmpl)) gen_endvirtual(funcsp); XTDumpTab(funcsp); intermed_head = NULL; dag_rundown(); oFree(); theCurrentFunc = oldCurrentFunc; if (blockCount > maxBlocks) maxBlocks = blockCount; if (tempCount > maxTemps) maxTemps = tempCount; }