static void createCaller(void) { FUNCTIONCALL *params = Alloc(sizeof(FUNCTIONCALL)); TYPE *args = realArgs(lambdas->func); SYMBOL *func = makeID(sc_member, args, NULL, overloadNameTab[CI_FUNC]); SYMBOL *lambdaCall = search(isstructured(basetype(lambdas->func->tp)->btp) ? "__lambdaCallS" : "__lambdaCall", globalNameSpace->syms); BLOCKDATA block1, block2; STATEMENT *st; lambdaCall = (SYMBOL *)lambdaCall->tp->syms->table[0]->p; func->parentClass = lambdas->cls; func->linkage = lk_virtual; func->isInline = FALSE; func->omitFrame = TRUE; memset(&block1, 0, sizeof(BLOCKDATA)); memset(&block2, 0, sizeof(BLOCKDATA)); insertFunc(lambdas->cls, func); InsertInline(func); st = stmtNode(NULL, &block2, isstructured(basetype(lambdas->func->tp)->btp) ? st_expr : st_return); st->select = varNode(en_func, NULL); st->select->v.func = params; params->arguments = Alloc(sizeof(INITLIST)); params->arguments->exp = varNode(en_pc, lambdas->func); params->arguments->tp = &stdpointer; params->ascall = TRUE; params->sp = func; params->fcall = varNode(en_pc, lambdaCall); params->functp = func->tp; st = stmtNode(NULL, &block1, st_block); st->lower = block2.head; st->blockTail = block2.blockTail; func->inlineFunc.stmt = stmtNode(NULL, NULL, st_block); func->inlineFunc.stmt->lower = block1.head; func->inlineFunc.stmt->blockTail = block1.blockTail; }
SYMBOL *gen_mp_virtual_thunk(SYMBOL *vsp) { QUAD *oi = intermed_head, *ot = intermed_tail; LIST *v = mpthunklist; SYMBOL *sp; IMODE *ap1, *ap2; char buf[256]; while (v) { sp = (SYMBOL*)v->data; if (sp->value.i == vsp->value.classdata.vtabindex) if (isstructured(vsp->tp->btp) == isstructured(sp->tp->btp)) return sp; v = v->link; } intermed_head = intermed_tail = NULL; blockMax = 0; blockCount = tempCount = 0; exitBlock = 0; IncGlobalFlag(); sp = Alloc(sizeof(SYMBOL)); sp->storage_class = sc_static; sp->tp = vsp->tp; sp->value.i = vsp->value.classdata.vtabindex; //sprintf(buf, "@$mpt$%d$%d", sp->value.i, isstructured(sp->tp->btp)); sp->name = sp->decoratedName = litlate(buf); sp->errname = sp->decoratedName; sp->staticlabel = FALSE; sp->gennedvirtfunc = TRUE; v = (LIST *)Alloc(sizeof(LIST)); v->data = sp; v->link = mpthunklist; mpthunklist = v; DecGlobalFlag(); gen_virtual(sp, FALSE); addblock(i_goto); gen_icode(i_substack, NULL, ap2 = tempreg(ISZ_ADDR, 0), NULL); gen_icode(i_add, ap2, ap2 , make_immed(ISZ_NONE, isstructured(sp->tp->btp) ? ISZ_ADDR * 2 : ISZ_ADDR)); ap1 = indnode(ap2, ISZ_ADDR); gen_icode(i_assn, ap2 = tempreg(ISZ_ADDR, 0), ap1, 0); if (sp->value.classdata.baseofs) gen_icode(i_add, ap2, ap2, make_immed(ISZ_NONE, sp->value.classdata.baseofs)); ap1 = indnode(ap2, ISZ_ADDR); gen_icode(i_assn, ap2 = tempreg(ISZ_ADDR, 0), ap1, 0); gen_icode(i_add, ap2, ap2, make_immed(ISZ_NONE, sp->value.i)); ap1 = indnode(ap2, ISZ_ADDR); gen_icode(i_directbranch, 0, ap1, 0); addblock(i_ret); optimize(); rewrite_icode(); /* Translate to machine code & dump */ if (chosenAssembler->gen->post_function_gen) chosenAssembler->gen->post_function_gen(intermed_head); gen_endvirtual(sp); intermed_head = oi; intermed_tail = ot; return sp; }
static BOOLEAN isStandardLayout(TYPE *tp, SYMBOL **result) { if (isstructured(tp) && !hasVTab(basetype(tp)->sp) && !basetype(tp)->sp->vbaseEntries ) { int n; int access = -1; SYMBOL *found = NULL, *first; HASHREC *hr; n = FindBaseClassWithData(tp->sp, &found); if (n > 1) return FALSE; if (n) { SYMBOL *first = NULL; hr = basetype(found->tp)->syms->table[0]; while (hr) { SYMBOL *sp = (SYMBOL *)hr->p; if (!first) first = sp; if (sp->storage_class == sc_member || sp->storage_class == sc_mutable) { if (isstructured(sp->tp) && !isStandardLayout(sp->tp, NULL)) return FALSE; if (access != -1) { if (access != sp->access) return FALSE; } access = sp->access; } hr = hr->next; } if (first && isstructured(first->tp)) { BASECLASS *bc = found->baseClasses; while (bc) { if (comparetypes(bc->cls->tp, first->tp, TRUE)) return FALSE; bc = bc->next; } } } if (result) *result = found; return TRUE; } return FALSE; /* hasnonon-staticdatamembersoftypenon-standard-layoutclass(orarrayofsuchtypes)orreference, — has no virtual functions (10.3) and no virtual base classes (10.1), — has the same access control (Clause 11) for all non-static data members, — has no non-standard-layout base classes, — either has no non-static data members in the most derived class and at most one base class with non-static data members, or has no base classes with non-static data members, and — has no base classes of the same type as the ?rst non-static data member. */ }
static BOOLEAN trivialCopyAssignable(TYPE *tp) { if (isstructured(tp)) { HASHREC *hr; SYMBOL *ovl; BASECLASS * bc; ovl = search(overloadNameTab[assign - kw_new + CI_NEW ], basetype(tp)->syms); if (ovl) { if (!trivialFunc(ovl, FALSE) || !trivialFunc(ovl, TRUE)) return FALSE; } bc = basetype(tp)->sp->baseClasses; while (bc) { if (!trivialCopyAssignable(bc->cls->tp)) return FALSE; bc = bc->next; } hr = basetype(tp)->syms->table[0]; while (hr) { SYMBOL *sym = (SYMBOL *)hr->p; if (sym->storage_class == sc_mutable || sym->storage_class == sc_member) if (!trivialCopyAssignable(sym->tp)) return FALSE; hr = hr->next; } } return TRUE; }
EXPRESSION *anonymousVar(enum e_sc storage_class, TYPE *tp) { static int anonct = 1; char buf[256]; SYMBOL *rv = (SYMBOL *)Alloc(sizeof(SYMBOL)); // if ((storage_class == sc_localstatic || storage_class == sc_auto) && !theCurrentFunc) // { // storage_class = sc_static; // insertInitSym(rv); // } if (tp->size == 0 && isstructured(tp)) tp = basetype(tp)->sp->tp; rv->storage_class = storage_class; rv->tp = tp; rv->anonymous = TRUE; rv->allocate = !anonymousNotAlloc; rv->assigned = TRUE; rv->used = TRUE; if (theCurrentFunc) rv->value.i = theCurrentFunc->value.i; sprintf(buf,"$anontemp%d", anonct++); rv->name = litlate(buf); tp->size = basetype(tp)->size; if (theCurrentFunc && !inDefaultParam) InsertSymbol(rv, storage_class, FALSE, FALSE); SetLinkerNames(rv, lk_none); return varNode(storage_class == sc_auto || storage_class == sc_parameter ? en_auto : storage_class == sc_localstatic ? en_label : en_global, rv); }
static BOOLEAN nothrowConstructible(TYPE *tp) { if (isstructured(tp)) { SYMBOL *ovl; // recursion will have been taken care of elsewhere... ovl = search(overloadNameTab[CI_CONSTRUCTOR ], basetype(tp)->syms); if (ovl) { HASHREC *hr = ovl->tp->syms->table[0]; hr = basetype(ovl->tp)->syms->table[0]; while (hr) { SYMBOL *sp = (SYMBOL *)hr->p; HASHREC *hr1 = basetype(sp->tp)->syms->table[0]; if (matchesCopy(sp, FALSE) || matchesCopy(sp, TRUE) || !hr1->next || !hr1->next->next || ((SYMBOL *)hr1->next->next->p)->tp->type == bt_void) { if (sp->xcMode != xc_none) return FALSE; } hr = hr->next; } } } return TRUE; }
static BOOLEAN trivialDestructor(TYPE *tp) { if (isstructured(tp)) { HASHREC *hr; SYMBOL *ovl; BASECLASS *bc; ovl = search(overloadNameTab[CI_DESTRUCTOR ], basetype(tp)->syms); if (ovl) { ovl = (SYMBOL *)ovl->tp->syms->table[0]->p; if (!ovl->defaulted) return FALSE; } bc = basetype(tp)->sp->baseClasses; while (bc) { if (!trivialDestructor(bc->cls->tp)) return FALSE; bc = bc->next; } hr = basetype(tp)->syms->table[0]; while (hr) { SYMBOL *sym = (SYMBOL *)hr->p; if (sym->storage_class == sc_mutable || sym->storage_class == sc_member) if (!trivialDestructor(sym->tp)) return FALSE; hr = hr->next; } } return TRUE; }
static BOOLEAN is_polymorphic(LEXEME **lex, SYMBOL *funcsp, SYMBOL *sym, TYPE **tp, EXPRESSION **exp) { INITLIST *lst; BOOLEAN rv = FALSE; FUNCTIONCALL funcparams; memset(&funcparams, 0, sizeof(funcparams)); funcparams.sp = sym; *lex = getTypeList(*lex, funcsp, &funcparams.arguments); lst = funcparams.arguments; while (lst) { lst->tp = PerformDeferredInitialization(lst->tp, NULL); lst = lst->next; } if (funcparams.arguments && !funcparams.arguments-> next) { // yes references are literal types... if (isstructured(funcparams.arguments->tp)) rv = !! hasVTab(basetype(funcparams.arguments->tp)->sp); } *exp = intNode(en_c_i, rv); *tp = &stdint; return TRUE; }
static BOOLEAN trivialStructure(TYPE *tp) { if (isstructured(tp)) { return triviallyCopyable(tp) && trivialDefaultConstructor(tp); } return FALSE; }
// these next two rely on the CONST specifier on the func not being set up yet. static SYMBOL *createPtrCaller(SYMBOL *self) { // if the closure is copied then used on another thread yes the resulting // code can get into a race condition... INITLIST *args; FUNCTIONCALL *params = Alloc(sizeof(FUNCTIONCALL)); TYPE *pargs = realArgs(lambdas->func); SYMBOL *func = makeID(sc_static, pargs, NULL, "$ptrcaller"); SYMBOL *lambdaCall = search(isstructured(basetype(lambdas->func->tp)->btp) ? "__lambdaPtrCallS" : "__lambdaPtrCall", globalNameSpace->syms); BLOCKDATA block1, block2; STATEMENT *st; EXPRESSION *exp = varNode(en_label, self); lambdaCall = (SYMBOL *)lambdaCall->tp->syms->table[0]->p; func->parentClass = lambdas->cls; func->linkage = lk_virtual; func->isInline = FALSE; func->omitFrame = TRUE; deref(&stdpointer, &exp); memset(&block1, 0, sizeof(BLOCKDATA)); memset(&block2, 0, sizeof(BLOCKDATA)); insertFunc(lambdas->cls, func); st = stmtNode(NULL, &block2, isstructured(basetype(lambdas->func->tp)->btp) ? st_expr : st_return); st->select = varNode(en_func, NULL); st->select->v.func = params; params->arguments = Alloc(sizeof(INITLIST)); params->arguments->exp = varNode(en_pc, lambdas->func); params->arguments->tp = &stdpointer; args = Alloc(sizeof(INITLIST)); args->next = params->arguments; params->arguments = args; params->arguments->exp = exp; params->arguments->tp = &stdpointer; params->ascall = TRUE; params->sp = func; params->fcall = varNode(en_pc, lambdaCall); params->functp = func->tp; st = stmtNode(NULL, &block1, st_block); st->lower = block2.head; st->blockTail = block2. blockTail; func->inlineFunc.stmt = stmtNode(NULL, NULL, st_block); func->inlineFunc.stmt->lower = block1.head; func->inlineFunc.stmt->blockTail = block1.blockTail; return func; }
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 void InsertParameterThunks(SYMBOL *funcsp, BLOCK *b) { HASHREC *hr = basetype(funcsp->tp)->syms->table[0]; QUAD *old , *oldit; BLOCK *ocb = currentBlock; old = b->head->fwd; while (old != b->tail && old->dc.opcode != i_label) old = old->fwd; old = old->fwd; oldit = intermed_tail; intermed_tail = old->back; intermed_tail->fwd = NULL; currentBlock = b; while (hr) { SYMBOL *sp = (SYMBOL *)hr->p; if (sp->tp->type == bt_void || sp->tp->type == bt_ellipse || isstructured(sp->tp)) { hr = hr->next; continue; } if (!sp->imvalue || sp->imaddress) { hr = hr->next; continue; } if (funcsp->oldstyle && sp->tp->type == bt_float) { IMODE *right = (IMODE *)Alloc(sizeof(IMODE)); *right = *sp->imvalue; right->size = ISZ_DOUBLE; if (!chosenAssembler->arch->hasFloatRegs) { IMODE *dp = tempreg(ISZ_DOUBLE, 0); IMODE *fp = tempreg(ISZ_FLOAT, 0); /* oldstyle float gets promoted from double */ gen_icode(i_assn, dp, right, 0); gen_icode(i_assn, fp, dp, 0); gen_icode(i_assn, sp->imvalue, fp, 0); } } hr = hr->next; } currentBlock = ocb; if (old->back == b->tail) { b->tail = intermed_tail; } old->back = intermed_tail; intermed_tail->fwd = old; intermed_tail = oldit; }
static BOOLEAN is_base_of(LEXEME **lex, SYMBOL *funcsp, SYMBOL *sym, TYPE **tp, EXPRESSION **exp) { INITLIST *lst; BOOLEAN rv = FALSE; FUNCTIONCALL funcparams; memset(&funcparams, 0, sizeof(funcparams)); funcparams.sp = sym; *lex = getTypeList(*lex, funcsp, &funcparams.arguments); lst = funcparams.arguments; while (lst) { lst->tp = PerformDeferredInitialization(lst->tp, NULL); lst = lst->next; } if (funcparams.arguments && funcparams.arguments-> next && !funcparams.arguments->next->next) { if (isstructured(funcparams.arguments->tp) && isstructured(funcparams.arguments->next->tp)) rv = classRefCount(basetype(funcparams.arguments->tp)->sp, basetype(funcparams.arguments->next->tp)->sp) != 0; } *exp = intNode(en_c_i, rv); *tp = &stdint; return TRUE; }
static BOOLEAN is_class(LEXEME **lex, SYMBOL *funcsp, SYMBOL *sym, TYPE **tp, EXPRESSION **exp) { INITLIST *lst; BOOLEAN rv = FALSE; FUNCTIONCALL funcparams; memset(&funcparams, 0, sizeof(funcparams)); funcparams.sp = sym; *lex = getTypeList(*lex, funcsp, &funcparams.arguments); if (funcparams.arguments && !funcparams.arguments-> next) { rv = isstructured(funcparams.arguments->tp) && basetype(funcparams.arguments->tp)->type != bt_union; } *exp = intNode(en_c_i, rv); *tp = &stdint; return TRUE; }
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 BOOLEAN is_literal(LEXEME **lex, SYMBOL *funcsp, SYMBOL *sym, TYPE **tp, EXPRESSION **exp) { INITLIST *lst; BOOLEAN rv = FALSE; FUNCTIONCALL funcparams; memset(&funcparams, 0, sizeof(funcparams)); funcparams.sp = sym; *lex = getTypeList(*lex, funcsp, &funcparams.arguments); if (funcparams.arguments && !funcparams.arguments-> next) { // yes references are literal types... rv = !isstructured(funcparams.arguments->tp); } *exp = intNode(en_c_i, rv); *tp = &stdint; return TRUE; }
/* A trivially copyable class is a class that: — has no non-trivial copy constructors (12.8), — has no non-trivial move constructors (12.8), — has no non-trivial copy assignment operators (13.5.3, 12.8), — has no non-trivial move assignment operators (13.5.3, 12.8), and — has a trivial destructor (12.4). A trivial class is a class that has a trivial default constructor (12.1) and is trivially copyable. */ static BOOLEAN trivialStructureWithBases(TYPE *tp) { if (isstructured(tp)) { BASECLASS *bc; if (!trivialStructure(tp)) return FALSE; bc = basetype(tp)->sp->baseClasses; while (bc) { if (!trivialStructureWithBases(bc->cls->tp)) return FALSE; bc = bc->next; } } return TRUE; }
static BOOLEAN trivialDefaultConstructor(TYPE *tp) { if (isstructured(tp)) { HASHREC *hr; SYMBOL *ovl; BASECLASS *bc; ovl = search(overloadNameTab[CI_CONSTRUCTOR ], basetype(tp)->syms); if (ovl) { HASHREC *hr = ovl->tp->syms->table[0]; while (hr) { SYMBOL *sym = (SYMBOL *)hr->p; HASHREC *hr1 = basetype(sym->tp)->syms->table[0]; if (!hr1->next || !hr1->next->next || ((SYMBOL *)hr1->next->next->p)->tp->type == bt_void) if (!sym->defaulted) return FALSE; else break; hr = hr->next; } } bc = basetype(tp)->sp->baseClasses; while (bc) { if (!trivialDefaultConstructor(bc->cls->tp)) return FALSE; bc = bc->next; } hr = basetype(tp)->syms->table[0]; while (hr) { SYMBOL *sym = (SYMBOL *)hr->p; if (sym->storage_class == sc_mutable || sym->storage_class == sc_member) if (!trivialDefaultConstructor(sym->tp)) return FALSE; hr = hr->next; } } return TRUE; }
BOOL checktypeassign(TYPE *typ1, TYPE *typ2) { /* this is so we can put an ampersand in front of a func name we are using */ if (isfuncptr(typ1) && isfuncptr(typ2)) return TRUE; while (typ1 && typ2) { typ1 = basetype(typ1); typ2 = basetype(typ2); if (isarithmetic(typ1) && isarithmetic(typ2)) return TRUE; if (isstructured(typ1) && comparetypes(typ1, typ2, TRUE)) return TRUE; typ1 = typ1->btp; typ2 = typ2->btp; } if (!typ1 && !typ2) return (TRUE); return (FALSE); }
static BOOLEAN isPOD(TYPE *tp) { SYMBOL *found = NULL; if (isStandardLayout(tp, found) && trivialStructureWithBases(tp)) { if (found) { HASHREC *hr = basetype(found->tp)->syms->table; while (hr) { SYMBOL *sym = (SYMBOL *)hr->p; if (isstructured(sym->tp) && !trivialStructureWithBases(sym->tp)) return FALSE; hr = hr->next; } } return TRUE; } return FALSE; }
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; } }
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; }
BOOL comparetypes(TYPE *typ1, TYPE *typ2, int exact) { if (typ1->type == bt_any || typ2->type == bt_any) return TRUE; if (typ1->type == bt_typedef) typ1 = basetype(typ1); if (typ2->type == bt_typedef) typ2 = basetype(typ2); if (isref(typ1)) typ1 = basetype(typ1)->btp; if (isref(typ2)) typ2 = basetype(typ2)->btp; if (ispointer(typ1) && ispointer(typ2)) if (exact) { int arr = FALSE; int first = TRUE; while (ispointer(typ1) && ispointer(typ2)) { if (!first && (exact == 1)) if (isconst(typ2) && !isconst(typ1) || isvolatile(typ2) && !isvolatile(typ1)) return FALSE; first = FALSE; typ1 = basetype(typ1); typ2 = basetype(typ2); if (typ1->type != typ2->type) return FALSE; if (arr && typ1->array != typ2->array) return FALSE; if (arr && typ1->size != typ2->size) return FALSE; arr |= typ1->array | typ2->array; typ1 = typ1->btp; typ2 = typ2->btp; } if ((exact == 1) && (isconst(typ2) && !isconst(typ1) || isvolatile(typ2) && !isvolatile(typ1))) return FALSE; return comparetypes(typ1, typ2, TRUE); } else return TRUE; typ1 = basetype(typ1); typ2 = basetype(typ2); if (exact && (isfunction(typ1) || isfuncptr(typ1)) && (isfunction(typ2) || isfuncptr(typ2))) { HASHREC *hr1; HASHREC *hr2; typ1 = basetype(typ1); typ2 = basetype(typ2); if (ispointer(typ1)) typ1 = basetype(typ1->btp); if (ispointer(typ2)) typ2 = basetype(typ2->btp); if (!comparetypes(typ1->btp, typ2->btp, exact)) return FALSE; hr1 = typ1->syms->table[0]; hr2 = typ2->syms->table[0]; while (hr1 && hr2) { SYMBOL *sp1 = (SYMBOL *)hr1->p; SYMBOL *sp2 = (SYMBOL *)hr2->p; if (!comparetypes(sp1->tp, sp2->tp, exact)) return FALSE; hr1 = hr1->next; hr2 = hr2->next; } if (hr1 || hr2) return FALSE; return TRUE; } if (cparams.prm_cplusplus) { if (typ1->scoped != typ2->scoped) return FALSE; if (typ1->type == bt_enum) { if (typ2->type == bt_enum) return typ1->sp == typ2->sp; else return isint(typ2); } else if (typ2->type == bt_enum) { return isint(typ1); } if (typ1->type == typ2->type && typ1->type == bt_memberptr) { if (typ1->sp != typ2->sp) { if (classRefCount(typ2->sp, typ1->sp) != 1) return FALSE; } return comparetypes(typ1->btp, typ2->btp, exact); } } if (typ1->type == typ2->type && (isstructured(typ1) || exact && typ1->type == bt_enum)) return typ1->sp == typ2->sp; if (typ1->type == typ2->type || !exact && isarithmetic(typ2) && isarithmetic(typ1)) return TRUE; if (isfunction(typ1) && isfunction(typ2) && typ1->sp->linkage == typ2->sp->linkage) return TRUE; else if (!exact && (ispointer(typ1) && (isfuncptr(typ2) || isfunction(typ2) || isint(typ2)) || ispointer(typ2) && (isfuncptr(typ1) || isfunction(typ1) || isint(typ1)))) return (TRUE); else if (typ1->type == bt_enum && isint(typ2)) { return TRUE; } else if (typ2->type == bt_enum && isint(typ1)) { return TRUE; } return FALSE; }
static void renameToTemps(SYMBOL *funcsp) { HASHTABLE *temp = funcsp->inlineFunc.syms; if (!cparams.prm_optimize || functionHasAssembly) return; /* if there is a setjmp in the function, no variable gets moved into a reg */ if (setjmp_used) return; while (temp) { HASHREC *hr = temp->table[0]; while (hr) { SYMBOL *sp = (SYMBOL *)hr->p; TYPE *tp; /* needed for pointer aliasing */ if (!sp->imvalue && basetype(sp->tp)->type != bt_memberptr && !isstructured(sp->tp) && sp->tp->type != bt_ellipse && sp->tp->type != bt_aggregate) { if (sp->storage_class != sc_auto && sp->storage_class != sc_register) { IncGlobalFlag(); } if (sp->imaddress) { IMODE *im = Alloc(sizeof(IMODE)); *im = *sp->imaddress; im->size = sizeFromType(sp->tp); im->mode = i_direct; sp->imvalue = im; } else if (sp->imind) { IMODE *im = Alloc(sizeof(IMODE)); *im = *sp->imind->im; im-> size = ISZ_ADDR; im->mode = i_direct; sp->imvalue = im; } else sp->imvalue = tempreg(sizeFromType(sp->tp), FALSE); if (sp->storage_class != sc_auto && sp->storage_class != sc_register) { DecGlobalFlag(); } } tp = sp->tp; if (tp->type == bt_typedef) tp = tp->btp; if (!sp->pushedtotemp && sp->storage_class != sc_parameter && !sp->imaddress && !sp->inasm && ((chosenAssembler->arch->hasFloatRegs || tp->type < bt_float) && tp->type < bt_void || basetype(tp)->type == bt_pointer && basetype(tp)->btp->type != bt_func || isref(tp)) && (sp->storage_class == sc_auto || sp->storage_class == sc_register) && !sp->usedasbit) { /* this works because all IMODES refering to the same * variable are the same, at least until this point * that will change when we start inserting temps */ EXPRESSION *ep = tempenode(); ep->v.sp->tp = sp->tp; ep->right = (EXPRESSION *)sp; /* marking both the orignal var and the new temp as pushed to temp*/ sp->pushedtotemp = TRUE ; ep->v.sp->pushedtotemp = TRUE; sp->allocate = FALSE; if (sp->imvalue) { ep->isvolatile = sp->imvalue->offset->isvolatile; ep->isrestrict = sp->imvalue->offset->isrestrict; sp->imvalue->offset = ep ; } if (sp->imind) { IMODELIST *iml = sp->imind; ep->isvolatile = sp->imind->im->offset->isvolatile; ep->isrestrict = sp->imind->im->offset->isrestrict; while (iml) { iml->im->offset = ep; iml = iml->next; } } ep->v.sp->imvalue = sp->imvalue; } hr = hr->next; } temp = temp->next; } }
TYPE *destSize(TYPE *tp1, TYPE *tp2, EXPRESSION **exp1, EXPRESSION **exp2, BOOLEAN minimizeInt, TYPE *atp) /* * compare two types and determine if they are compatible for purposes * of the current operation. Return an appropriate type. Also checks for * dangerous pointer conversions... */ { int isctp1, isctp2; if (tp1->type == bt_any) return tp1; if (tp2->type == bt_any) return tp2; if (isvoid(tp1) || isvoid(tp2)) { error(ERR_NOT_AN_ALLOWED_TYPE); return tp1; } if (isref(tp1)) tp1 = basetype(tp1)->btp; if (isref(tp2)) tp2 = basetype(tp2)->btp; tp1 = basetype(tp1); tp2 = basetype(tp2); isctp1 = isarithmetic(tp1); isctp2 = isarithmetic(tp2); /* if (isctp1 && isctp2 && tp1->type == tp2->type) return tp1 ; */ if (tp1->type >= bt_float || tp2->type >= bt_float) { int isim1 = tp1->type >= bt_float_imaginary && tp1->type <= bt_long_double_imaginary; int isim2 = tp2->type >= bt_float_imaginary && tp2->type <= bt_long_double_imaginary; if (isim1 && !isim2 && tp2->type < bt_float_imaginary) { TYPE *tp ; if (tp1->type == bt_long_double_imaginary || tp2->type == bt_long_double) tp = &stdlongdoublecomplex; else if (tp1->type == bt_double_imaginary || tp2->type == bt_double || tp1->type == bt_long_long || tp1->type == bt_unsigned_long_long) tp = &stddoublecomplex; else tp = &stdfloatcomplex; if (exp1) cast(tp, exp1); if (exp2) cast(tp, exp2); return tp; } else if (isim2 && !isim1 && tp1->type < bt_float_imaginary) { TYPE *tp ; if (tp2->type == bt_long_double_imaginary || tp1->type == bt_long_double) tp = &stdlongdoublecomplex; else if (tp2->type == bt_double_imaginary || tp1->type == bt_double || tp1->type == bt_long_long || tp1->type == bt_unsigned_long_long) tp = &stddoublecomplex; else tp = &stdfloatcomplex; if (exp1) cast(tp, exp1); if (exp2) cast(tp, exp2); return tp; } else if (tp1->type > tp2->type) { if (exp2) cast(tp1, exp2); } else if (tp1->type < tp2->type) { if (exp1) cast(tp2, exp1); } if (tp1->type == bt_long_double_complex && isctp2) return tp1; if (tp2->type == bt_long_double_complex && isctp1) return tp2; if (tp1->type == bt_long_double_imaginary && isim2) return tp1; if (tp2->type == bt_long_double_imaginary && isim1) return tp2; if (tp1->type == bt_long_double && isctp2) return tp1; if (tp2->type == bt_long_double && isctp1) return tp2; if (tp1->type == bt_double_complex && isctp2) return tp1; if (tp2->type == bt_double_complex && isctp1) return tp2; if (tp1->type == bt_double_imaginary && isim2) return tp1; if (tp2->type == bt_double_imaginary && isim1) return tp2; if (tp1->type == bt_double && isctp2) return tp1; if (tp2->type == bt_double && isctp1) return tp2; if (tp1->type == bt_float_complex && isctp2) return tp1; if (tp2->type == bt_float_complex && isctp1) return tp2; if (tp1->type == bt_float_imaginary && isim2) return tp1; if (tp2->type == bt_float_imaginary && isim1) return tp2; if (tp1->type == bt_float && isctp2) return tp1; if (tp2->type == bt_float && isctp1) return tp2; } if (isctp1 && isctp2) { TYPE *rv ; enum e_bt t1, t2; t1 = tp1->type; t2 = tp2->type; /* if (cparams.prm_cplusplus && (t1 == bt_enum || t2 == bt_enum)) { if (t1 == t2) { if (tp1->sp->mainsym == tp2->sp->mainsym) { return tp1; } genmismatcherror(ERR_ENUMMISMATCH, tp1, tp2); } } */ if (t1 == bt_enum) t1= bt_int; if (t2 == bt_enum) t2= bt_int; if (t1 == bt_wchar_t) t1 = bt_unsigned; if (t2 == bt_wchar_t) t2 = bt_unsigned; if (t1 < bt_int) t1= bt_int; if (t2 < bt_int) t2= bt_int; t1 = imax(t1, t2); rv = inttype(t1); if (rv->type != tp1->type && exp1) cast(rv, exp1); if (rv->type != tp2->type && exp2) cast(rv,exp2); return rv; } else { /* have a pointer or other exceptional case*/ if (tp1->type == bt_void && tp2->type == bt_void) return tp1; if (tp1->type <= bt_unsigned_long_long && ispointer(tp2)) { if (!ispointer(tp1)) cast(tp2, exp1); return tp2; } if (tp2->type <= bt_unsigned_long_long && ispointer(tp1)) { if (!ispointer(tp2)) cast(tp1, exp2); return tp1; } if (isstructured(tp1)) { return tp2; /* if (comparetypes(tp1, tp2, FALSE)) return tp1; if (cparams.prm_cplusplus) { cppcast(tp2, tp1, exp1, FALSE, ERR_CPPMISMATCH); } else error(ERR_ILL_STRUCTURE_OPERATION); return tp2; */ } if (isstructured(tp2)) { return tp1; /* if (comparetypes(tp1, tp2, FALSE)) return tp2; if (cparams.prm_cplusplus) { cppcast(tp1, tp2, exp1, FALSE, ERR_CPPMISMATCH); } else error(ERR_ILL_STRUCTURE_OPERATION); return tp1; */ } if (isfunction(tp1)) if (isfunction(tp2) || ispointer(tp2)) return tp1; if (isfunction(tp2)) if (isfunction(tp1) || ispointer(tp1)) return tp2; if (ispointer(tp1)) if (ispointer(tp2)) { /* if (tp1->type != tp2->type || !comparetypes(tp1->btp, tp2->btp, TRUE)) generror(ERR_SUSPICIOUS, 0, 0); */ return tp1; } } return tp1; }
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 link_extendedtype(TYPE *tp1) { TYPE *tp = basetype(tp1); if (tp->type == bt_pointer) { if (tp->vla) { int m = link_puttype(tp->btp); tp1->dbgindex = emit_type_ieee("T7,%X,T%X,T2A",tp->size,m); } else if (tp->array) { int m = link_puttype(tp->btp); tp1->dbgindex = emit_type_ieee("T6,%X,T%X,T2A,%d,%d",tp->size,m,0,tp->size/basetype(tp)->btp->size); } else { int m = link_puttype(tp->btp); tp1->dbgindex = emit_type_ieee("T1,%X,T%X",tp->size,m); } } else if (isfunction(tp)) { tp1->dbgindex = dumpFunction(tp); } else { int n = tp1->dbgindex = typeIndex++; if (tp->hasbits) { int m = link_BasicType(tp); emit_record_ieee("ATT%X,T3,%X,T%X,%d,%d.\r\n",n, tp->size, m, tp->startbit, tp->bits); } else if (isstructured(tp)) { int sel; if (tp->type == bt_union) { sel = 5; } else { sel = 4; } if (tp->syms) dumpStructFields(sel, n, tp->size, tp->syms->table[0]); else dumpStructFields(sel, n, tp->size, NULL); emit_record_ieee("NT%X,%02X%s.\r\n", n, strlen(tp->sp->name), tp->sp->name); } else if (tp->type == bt_ellipse) { // ellipse results in no debug info } else // enum { int m; if (tp->type == bt_enum) if (tp->btp) m = link_BasicType(tp->btp); else m = 42; else m = link_BasicType(tp); if (tp->syms) dumpEnumFields(8, n, m, tp->size, tp->syms->table[0]); else dumpEnumFields(8, n, m, tp->size, NULL); emit_record_ieee("NT%X,%02X%s.\r\n", n, strlen(tp->sp->name), tp->sp->name); } } }
char *mangleType (char *in, TYPE *tp, BOOLEAN first) { char nm[4096]; int i; HASHREC *hr ; if(!tp) { sprintf(in, "%d%s", strlen("initializer-list"), "initializer-list"); in += strlen(in); } else if (tp->type == bt_typedef) { in = mangleType(in, tp->btp, FALSE); } else if (isstructured(tp) && basetype(tp)->sp->templateLevel) { { if (isconst(tp)) *in++ = 'x'; if (isvolatile(tp)) *in++ = 'y'; if (islrqual(tp)) *in++ = 'r'; if (isrrqual(tp)) *in++ = 'R'; } in = mangleTemplate(in, basetype(tp)->sp, basetype(tp)->sp->templateParams); } else { // if (ispointer(tp) || isref(tp)) // { // if (basetype(tp)->btp) // { // if (isconst(basetype(tp)->btp)) // *in++ = 'x'; // if (isvolatile(basetype(tp)->btp)) // *in++ = 'y'; // } // } // if (isfunction(tp)) { if (isconst(tp)) *in++ = 'x'; if (isvolatile(tp)) *in++ = 'y'; if (islrqual(tp)) *in++ = 'r'; if (isrrqual(tp)) *in++ = 'R'; } tp = basetype(tp); switch (tp->type) { /* case bt_templateplaceholder: tplPlaceholder(nm, tp->lst.head->name, tp->lst.tail); sprintf(buf, "%d%s", strlen(nm), nm); buf += strlen(buf); break; */ case bt_func: case bt_ifunc: if (basetype(tp)->sp && basetype(tp)->sp->parentClass && !first) { *in++ = 'M'; in = getName(in, tp->sp->parentClass); in += strlen(in); } *in++ = 'q'; hr = tp->syms->table[0]; while (hr) { SYMBOL *sp = (SYMBOL *)hr->p; if (!sp->thisPtr) in = mangleType(in, sp->tp, TRUE); hr = hr->next ; } *in++ = '$'; // return value in = mangleType(in, tp->btp, TRUE); break; case bt_memberptr: *in++ = 'M'; in = getName(in, tp->sp); if (isfunction(tp->btp)) { *in++ = 'q'; hr = basetype(tp->btp)->syms->table[0]; while (hr) { SYMBOL *sp = (SYMBOL *)hr->p; if (!sp->thisPtr) in = mangleType(in, sp->tp, TRUE); hr = hr->next ; } *in++ = '$'; in = mangleType (in, tp->btp->btp, TRUE); } else { *in++ = '$'; in = mangleType (in, basetype(tp)->btp, TRUE); } break; case bt_enum: case bt_struct: case bt_union: case bt_class: in = getName(in, tp->sp); break; case bt_bool: in = lookupName(in, "bool"); in += strlen(in); break; case bt_unsigned_short: *in++ = 'u'; case bt_short: *in++ = 's'; break; case bt_unsigned: *in++ = 'u'; case bt_int: *in++ = 'i'; break; case bt_char16_t: *in++ = 'h'; break; case bt_char32_t: *in++ = 'H'; break; case bt_unsigned_long: *in++ = 'u'; case bt_long: *in++ = 'l'; break; case bt_unsigned_long_long: *in++ = 'u'; case bt_long_long: *in++ = 'L'; break; case bt_unsigned_char: *in++ = 'u'; case bt_char: *in++ = 'c'; break; case bt_signed_char: *in++ = 'S'; *in++ = 'c'; break; case bt_wchar_t: *in++ = 'C'; break; case bt_float_complex: *in++ = 'F'; break; case bt_double_complex: *in++ = 'D'; break; case bt_long_double_complex: *in++ = 'G'; break; case bt_float: *in++ = 'f'; break; case bt_double: *in++ = 'd'; break; case bt_long_double: *in++ = 'g'; break; case bt_pointer: if (tp->nullptrType) { in = lookupName(in, "nullptr_t"); in += strlen(in); } else { if (first|| !tp->array) { *in++ = 'p'; } else { sprintf(in,"A%ld",tp->btp->size ? tp->size / tp->btp->size : 0); in += strlen(in); } in = mangleType(in, tp->btp, FALSE); } break; case bt_far: *in++ = 'P'; in = mangleType(in, tp->btp, FALSE); break; case bt_lref: *in++ = 'r'; in = mangleType(in, tp->btp, FALSE); break; case bt_rref: *in++ = 'R'; in = mangleType(in, tp->btp, FALSE); break; case bt_ellipse: *in++ = 'e'; break; case bt_void: case bt_any: *in++ = 'v'; break; case bt_templateparam: in = getName(in, tp->templateParam->p->sym); break; case bt_templateselector: { TEMPLATESELECTOR *s = tp->sp->templateSelector; char *p; s = s->next; if (s->isTemplate) p = mangleTemplate(nm, s->sym, s->templateParams); else p = getName(nm, s->sym); p[0] =0; if (strlen(nm) > sizeof(nm)) p = mangleTemplate(nm, s->sym, s->templateParams); s = s->next ; while (s) { strcat(nm , "@"); strcat(nm , s->name); s= s->next; } p = nm; while (isdigit(*p)) p++; sprintf(in, "%d%s", strlen(p), p); in += strlen(in); } break; case bt_templatedecltype: // the index is being used to make names unique so two decltypes won't collide when storing them // in a symbol table... declTypeIndex = (declTypeIndex + 1) %1000; *in++ = 'E'; sprintf(in, "%03d", declTypeIndex); in += 3; break; case bt_aggregate: in = getName(in, tp->sp); break; default: diag("mangleType: unknown type"); break; } } *in= 0; return in; }
static BOOLEAN is_convertible_to(LEXEME **lex, SYMBOL *funcsp, SYMBOL *sym, TYPE **tp, EXPRESSION **exp) { BOOLEAN rv = TRUE; FUNCTIONCALL funcparams; memset(&funcparams, 0, sizeof(funcparams)); funcparams.sp = sym; *lex = getTypeList(*lex, funcsp, &funcparams.arguments); if (funcparams.arguments && funcparams.arguments->next && !funcparams.arguments->next->next) { TYPE *from = funcparams.arguments->tp; TYPE *to = funcparams.arguments->next->tp; if (isref(from) && isref(to)) { if (basetype(to)->type == bt_lref) { if (basetype(from)->type == bt_rref) rv = FALSE; } } else if (isref(from)) rv = FALSE; if (isfunction(from)) from = basetype(from)->btp; if (rv) { while (isref(from)) from = basetype(from)->btp; while (isref(to)) to = basetype(to)->btp; rv = comparetypes(to, from, FALSE); if (!rv && isstructured(from) && isstructured(to)) { if (classRefCount(basetype(to)->sp, basetype(from)->sp) == 1) rv = TRUE; } if (!rv && isstructured(from)) { SYMBOL *sp = search("$bcall", basetype(from)->syms); if (sp) { HASHREC *hr = sp->tp->syms->table[0]; while (hr) { if (comparetypes(basetype(((SYMBOL *)hr->p)->tp)->btp, to, FALSE)) { rv= TRUE; break; } hr = hr->next; } } } } } else { rv = FALSE; } *exp = intNode(en_c_i, rv); *tp = &stdint; return TRUE; }