/* * Define everything needed to print out some data (or text). * This means segment, alignment, visibility, etc. */ void defloc(struct symtab *sp) { static char *loctbl[] = { "text", "data", "data" }; TWORD t; char *n; int s; if (sp == NULL) { lastloc = -1; return; } t = sp->stype; s = ISFTN(t) ? PROG : ISCON(cqual(t, sp->squal)) ? RDATA : DATA; if (s != lastloc) printf(" .%s\n", loctbl[s]); lastloc = s; while (ISARY(t)) t = DECREF(t); n = sp->soname ? sp->soname : exname(sp->sname); if (sp->sclass == EXTDEF) printf(" .globl %s\n", n); if (ISFTN(sp->stype) || talign(sp->stype, sp->ssue) > ALCHAR) printf(".even\n"); if (sp->slevel == 0) { printf("%s:\n", n); } else { printf(LABFMT ":\n", sp->soffset); } }
/* * Define everything needed to print out some data (or text). * This means segment, alignment, visibility, etc. */ void defloc(struct symtab *sp) { char *nextsect = NULL; /* notyet */ static char *loctbl[] = { "text", "data", "section .rodata" }; static int lastloc = -1; TWORD t; int s; if (sp == NULL) { lastloc = -1; return; } t = sp->stype; s = ISFTN(t) ? PROG : ISCON(cqual(t, sp->squal)) ? RDATA : DATA; if (nextsect) { printf(" .section %s\n", nextsect); nextsect = NULL; s = -1; } else if (s != lastloc) printf(" .%s\n", loctbl[s]); lastloc = s; if (sp->sclass == EXTDEF) printf(" .globl %s\n", sp->soname); if (sp->slevel == 0) printf("%s:\n", sp->soname); else printf(LABFMT ":\n", sp->soffset); }
/* * Do name mangling of a symbol table entry. * The resulting name is saved in soname. */ char * decoratename(struct symtab *sp, int type) { char *n; #define QNM(m,s) case m: n = s; break switch (type) { QNM(NM_NEW,"_Znwm"); QNM(NM_NWA,"_Znam"); QNM(NM_DEL,"_ZdlPv"); QNM(NM_DLA,"_ZdaPv"); case NM_NORMAL: /* Defined in defid() */ break; default: uerror("missed mangling %d\n", type); return ""; } if (type != NM_NORMAL) return addname(n); /* special non-mangled cases: * "C" linkage * main() function * variables outside namespaces and classes */ if (elnk == LINK_C || strcmp(sp->sname, "main") == 0 || (sp->sdown == spole && ISFTN(sp->stype) == 0)) { n = exname(sp->sname); return addname(n); } /* Compute the mangled name for other symbols */ nmptr = 0; subptr = 0; nmch('_'); nmch('Z'); if (sp->sdown != NULL) { nmch('N'); recnpsh(sp->sdown); } pshsln(sp->sname); if (sp->sdown != NULL) nmch('E'); if (ISFTN(sp->stype) && sp->sdf->dfun) pshargs(sp->sdf->dfun); nmch(0); return addname(nmblk); }
/* * output a nice description of the type of t */ void tprint(FILE *fp, TWORD t, TWORD q) { static char * tnames[] = { "undef", "farg", "char", "uchar", "short", "ushort", "int", "unsigned", "long", "ulong", "longlong", "ulonglong", "float", "double", "ldouble", "strty", "unionty", "enumty", "moety", "void", "signed", /* pass1 */ "bool", /* pass1 */ "fimag", /* pass1 */ "dimag", /* pass1 */ "limag", /* pass1 */ "fcomplex", /* pass1 */ "dcomplex", /* pass1 */ "lcomplex", /* pass1 */ "enumty", /* pass1 */ "?", "?" }; for(;; t = DECREF(t), q = DECREF(q)) { if (ISCON(q)) fputc('C', fp); if (ISVOL(q)) fputc('V', fp); if (ISPTR(t)) fprintf(fp, "PTR "); else if (ISFTN(t)) fprintf(fp, "FTN "); else if (ISARY(t)) fprintf(fp, "ARY "); else { fprintf(fp, "%s%s%s", ISCON(q << TSHIFT) ? "const " : "", ISVOL(q << TSHIFT) ? "volatile " : "", tnames[t]); return; } } }
/* * Called with a function call with arguments as argument. * This is done early in buildtree() and only done once. * Returns p. */ NODE * funcode(NODE *p) { NODE *l, *r; TWORD t; int i; nsse = ngpr = nrsp = 0; /* Check if hidden arg needed */ /* If so, add it in pass2 */ if ((l = p->n_left)->n_type == INCREF(FTN)+STRTY || l->n_type == INCREF(FTN)+UNIONTY) { int ssz = tsize(BTYPE(l->n_type), l->n_df, l->n_ap); if (ssz > 2*SZLONG) ngpr++; } /* Convert just regs to assign insn's */ p->n_right = argput(p->n_right); /* Must sort arglist so that STASG ends up first */ /* This avoids registers being clobbered */ while (argsort(p->n_right)) ; /* Check if there are varargs */ if (nsse || l->n_df == NULL || l->n_df->dfun == NULL) { ; /* Need RAX */ } else { union arglist *al = l->n_df->dfun; for (; al->type != TELLIPSIS; al++) { if ((t = al->type) == TNULL) return p; /* No need */ if (ISSOU(BTYPE(t))) al++; for (i = 0; t > BTMASK; t = DECREF(t)) if (ISARY(t) || ISFTN(t)) i++; if (i) al++; } } /* Always emit number of SSE regs used */ l = movtoreg(bcon(nsse), RAX); if (p->n_right->n_op != CM) { p->n_right = block(CM, l, p->n_right, INT, 0, 0); } else { for (r = p->n_right; r->n_left->n_op == CM; r = r->n_left) ; r->n_left = block(CM, l, r->n_left, INT, 0, 0); } return p; }
/* * Define everything needed to print out some data (or text). * This means segment, alignment, visibility, etc. */ void defloc(struct symtab *sp) { extern char *nextsect; static int lastloc = -1; TWORD t; char *n; int s; if (sp == NULL) { lastloc = -1; return; } t = sp->stype; s = ISFTN(t) ? PROG : ISCON(cqual(t, sp->squal)) ? RDATA : DATA; if (nextsect) { printf("\t.section %s\n", nextsect); nextsect = NULL; s = -1; } else if (s != lastloc) printf("\t.%s\n", loctbl[s]); lastloc = s; while (ISARY(t)) t = DECREF(t); s = ISFTN(t) ? ALINT : talign(t, sp->ssue); if (s > ALCHAR) printf("\t.align\t%d\n", s / ALCHAR); n = sp->soname ? sp->soname : sp->sname; if (sp->sclass == EXTDEF) printf("\t.export %s, %s\n", n, ISFTN(t)? "code" : "data"); if (sp->slevel == 0) printf("\t.type\t%s, @%s\n\t.label %s\n", n, ISFTN(t)? "function" : "object", n); else printf("\t.type\t" LABFMT ", @%s\n\t.label\t" LABFMT "\n", sp->soffset, ISFTN(t)? "function" : "object", sp->soffset); }
/* * Define everything needed to print out some data (or text). * This means segment, alignment, visibility, etc. */ void defloc(struct symtab *sp) { char *n; if (ISFTN(sp->stype)) return; /* XXX until fixed */ n = getexname(sp); if (sp->sclass == EXTDEF) printf(" .globl %s\n", n); if (sp->slevel == 0) { #ifdef USE_GAS printf("\t.type %s,@%s\n", n, ISFTN(sp->stype) ? "function" : "object"); if (!ISFTN(sp->stype)) printf("\t.size %s," CONFMT "\n", n, tsize(sp->stype, sp->sdf, sp->sap)); #endif printf("%s:\n", n); } else printf(LABFMT ":\n", sp->soffset); }
/* * Define everything needed to print out some data (or text). * This means segment, alignment, visibility, etc. */ void defloc(struct symtab *sp) { char *n; n = sp->soname ? sp->soname : exname(sp->sname); #ifdef USE_GAS if (ISFTN(t)) printf("\t.type %s,%%function\n", n); #endif if (sp->sclass == EXTDEF) printf("\t.global %s\n", n); if (sp->slevel == 0) printf("%s:\n", n); else printf(LABFMT ":\n", sp->soffset); }
/* * Define everything needed to print out some data (or text). * This means segment, alignment, visibility, etc. */ void defloc(struct symtab *sp) { char *name; if ((name = sp->soname) == NULL) name = exname(sp->sname); if (ISFTN(sp->stype)) return; if (sp->sclass == EXTDEF) printf("\t.globl %s\n", name); if (sp->slevel == 0) printf("%s:\n", name); else printf(LABFMT ":\n", sp->soffset); }
/* * Compare a matching prototype for a function. */ static int cxxpcmp(struct symtab *sp, NODE *p) { union arglist *a1, *a2; int i; if (!ISFTN(sp->stype) || p->n_df == NULL || sp->sdf == NULL) return 0; /* no dimfun */ if ((a1 = sp->sdf->dfun) == NULL || (a2 = p->n_df->dfun) == NULL) return 0; /* no argument */ for (i = 0; ; i++) { if (a1[i].type == TNULL && a2[i].type == TNULL) return 1; /* equal prototypes */ if (a1[i].type != a2[i].type) return 1; /* unequal prototypes */ } }
/* * Define everything needed to print out some data (or text). * This means segment, alignment, visibility, etc. */ void defloc(struct symtab *sp) { char *name; if ((name = sp->soname) == NULL) name = exname(sp->sname); if (sp->sclass == EXTDEF) { printf("\t.globl %s\n", name); printf("\t.type %s,@%s\n", name, ISFTN(sp->stype)? "function" : "object"); } if (sp->slevel == 0) printf("%s:\n", name); else printf(LABFMT ":\n", sp->soffset); }
/* * Watch out for references to static members. */ NODE * cxxstructref(NODE *p, int f, char *n) { struct symtab *sp = strmemb(p->n_ap); if (sp == NULL) cerror("ref to unknown struct"); sp = sfind(n, sp); while (sp != NULL) { if (ISFTN(sp->stype) == 0) { if (sp->sclass == STATIC || sp->sclass == USTATIC) { tfree(p); return nametree(sp); } break; } sp = sfind(n, sp->snext); } return structref(p, f, n); }
/* * Compare a matching prototype for an argument tree. * Here we can expand to also do inexact matches. * Return 0 if equal, -1 if failed. */ static int cxxptreecmp(struct symtab *sp, NODE *p) { struct ckstr ckstr; union arglist *a1; if (!ISFTN(sp->stype) || sp->sdf == NULL || (a1 = sp->sdf->dfun) == NULL) return 0; /* no dimfun */ if (p == NULL && a1[0].type == TNULL) return 1; /* arg-less */ ckstr.rv = 0; ckstr.al = a1; flist(p, cxxckproto, &ckstr); if (ckstr.al[0].type != TNULL) return -1; /* arg number error */ return ckstr.rv; }
/* * Define everything needed to print out some data (or text). * This means segment, alignment, visibility, etc. */ void defloc(struct symtab *sp) { char *name; name = getexname(sp); if (sp->sclass == EXTDEF) { printf("\t.globl %s\n", name); if (ISFTN(sp->stype)) { printf("\t.type %s,@function\n", name); } else { printf("\t.type %s,@object\n", name); printf("\t.size %s,%d\n", name, (int)tsize(sp->stype, sp->sdf, sp->sap)/SZCHAR); } } if (sp->slevel == 0) printf("%s:\n", name); else printf(LABFMT ":\n", sp->soffset); }
/* * Define everything needed to print out some data (or text). * This means segment, alignment, visibility, etc. */ void defloc(struct symtab *sp) { static char *loctbl[] = { "text", "data", "data" }; TWORD t; char *n; int s; t = sp->stype; s = ISFTN(t) ? PROG : ISCON(cqual(t, sp->squal)) ? RDATA : DATA; if (s != lastloc) printf(" .%s\n", loctbl[s]); lastloc = s; n = sp->soname ? sp->soname : exname(sp->sname); if (sp->sclass == EXTDEF) printf(" .globl %s\n", n); if (sp->slevel == 0) { printf("%s:\n", n); } else { printf(LABFMT ":\n", sp->soffset); } }
void defloc(struct symtab *sp) { TWORD t; char *name; t = sp->stype; if ((name = sp->soname) == NULL) name = exname(sp->sname); if (!ISFTN(t)) { printf("\t.type %s,#object\n", name); printf("\t.size %s," CONFMT "\n", name, tsize(sp->stype, sp->sdf, sp->sap) / SZCHAR); } if (sp->sclass == EXTDEF) printf("\t.global %s\n", name); if (sp->slevel == 0) { printf("%s:\n", name); } else printf(LABFMT ":\n", sp->soffset); }
/* * Search for correct matching function in a struct depending on * argument list a. Return a call node for this function. * Do not touch neither f nor a. * return a name tree suitable for a function call. * We know here that f is a struct reference. */ NODE * cxxmatchftn(NODE *f, NODE *a) { struct attr *ap; struct symtab *sp; char *n = (char *)f->n_right->n_sp; f = f->n_left; if ((ap = attr_find(f->n_ap, ATTR_STRUCT)) == NULL) { uerror("undefined class"); sp = getsymtab(n, 0); } else sp = ap->amlist; sp = sfind(n, sp); while (sp != NULL) { if (ISFTN(sp->stype) && cxxptreecmp(sp, a) == 0) break; sp = sfind(n, sp->snext); } if (sp == NULL) uerror("undefined class member"); return nametree(sp); }
/* * code for the beginning of a function; a is an array of * indices in symtab for the arguments; n is the number * On m16k, space is allocated on stack for register arguments, * arguments are moved to the stack and symtab is updated accordingly. */ void bfcode(struct symtab **a, int n) { struct symtab *s; int i, r0l, r0h, a0, r2, sz, hasch, stk; int argoff = ARGINIT; if (cftnsp->stype == STRTY+FTN || cftnsp->stype == UNIONTY+FTN) { /* Function returns struct, adjust arg offset */ for (i = 0; i < n; i++) a[i]->soffset += SZPOINT(INT); } /* first check if there are 1-byte parameters */ for (hasch = i = 0; i < n && i < 6; i++) if (DEUNSIGN(a[i]->stype) == CHAR) hasch = 1; stk = r0l = r0h = a0 = r2 = 0; for (i = 0; i < n; i++) { s = a[i]; sz = tsize(s->stype, s->sdf, s->ssue); if (ISPTR(s->stype) && ISFTN(DECREF(s->stype))) sz = SZLONG; /* function pointers are always 32 */ if (stk == 0) switch (sz) { case SZCHAR: if (r0l) { if (r0h) break; argmove(s, 1); r0h = 1; } else { argmove(s, 0); r0l = 1; } continue; case SZINT: if (s->stype > BTMASK) { /* is a pointer */ if (a0) { if (r0l || hasch) { if (r2) break; argmove(s, R2); r2 = 1; } else { argmove(s, R0); r0l = r0h = 1; } } else { argmove(s, A0); a0 = 1; } } else if (r0l || hasch) { if (r2) { if (a0) break; argmove(s, A0); a0 = 1; } else { argmove(s, R2); r2 = 1; } } else { argmove(s, R0); r0l = r0h = 1; } continue; case SZLONG: if (r0l||r0h||r2) break; argmove(s, R0); r0l = r0h = r2 = 1; continue; default: break; } stk = 1; s->soffset = argoff; argoff += sz; } }
void prologue(struct interpass_prolog *ipp) { ftype = ipp->ipp_type; #if 0 if (ipp->ipp_regs > 0 && ipp->ipp_regs != MINRVAR) comperr("fix prologue register savings", ipp->ipp_regs); #endif printf(" RSEG CODE:CODE:REORDER:NOROOT(0)\n"); if (ipp->ipp_vis) printf(" PUBLIC %s\n", ipp->ipp_name); printf("%s:\n", ipp->ipp_name); #if 0 if (xsaveip) { /* Optimizer running, save space on stack */ addto = (p2maxautooff - AUTOINIT)/SZCHAR; printf(" enter #%d\n", addto); } else { #endif /* non-optimized code, jump to epilogue for code generation */ ftlab1 = getlab2(); ftlab2 = getlab2(); printf(" jmp.w " LABFMT "\n", ftlab1); deflab(ftlab2); } /* * End of block. */ void eoftn(struct interpass_prolog *ipp) { #if 0 if (ipp->ipp_regs != MINRVAR) comperr("fix eoftn register savings %x", ipp->ipp_regs); #endif // if (xsaveip == 0) addto = (p2maxautooff - AUTOINIT)/SZCHAR; /* return from function code */ //deflab(ipp->ipp_ip.ip_lbl); //XXX - is this necessary? /* If retval is a pointer and not a function pointer, put in A0 */ if (ISPTR(DECREF(ipp->ipp_type)) && !ISFTN(DECREF(DECREF(ipp->ipp_type)))) printf(" mov.w r0,a0\n"); /* struct return needs special treatment */ if (ftype == STRTY || ftype == UNIONTY) { comperr("fix struct return in eoftn"); } else printf(" exitd\n"); /* Prolog code */ // if (xsaveip == 0) { deflab(ftlab1); printf(" enter #%d\n", addto); printf(" jmp.w " LABFMT "\n", ftlab2); //} } /* * add/sub/... * * Param given: */ void hopcode(int f, int o) { char *str; switch (o) { case PLUS: str = "add"; break; case MINUS: str = "sub"; break; case AND: str = "and"; break; case OR: str = "or"; break; case ER: str = "xor"; break; default: comperr("hopcode2: %d", o); str = 0; /* XXX gcc */ } printf("%s.%c", str, f); }
/* * code for the beginning of a function; a is an array of * indices in symtab for the arguments; n is the number */ void bfcode(struct symtab **s, int cnt) { union arglist *al; struct symtab *sp; NODE *p, *r; TWORD t; int i, rno, typ; /* recalculate the arg offset and create TEMP moves */ /* Always do this for reg, even if not optimizing, to free arg regs */ nsse = ngpr = 0; nrsp = ARGINIT; if (cftnsp->stype == STRTY+FTN || cftnsp->stype == UNIONTY+FTN) { sp = cftnsp; if (argtyp(DECREF(sp->stype), sp->sdf, sp->sap) == STRMEM) { r = block(REG, NIL, NIL, LONG, 0, MKAP(LONG)); regno(r) = argregsi[ngpr++]; p = tempnode(0, r->n_type, r->n_df, r->n_ap); stroffset = regno(p); ecomp(buildtree(ASSIGN, p, r)); } } for (i = 0; i < cnt; i++) { sp = s[i]; if (sp == NULL) continue; /* XXX when happens this? */ switch (typ = argtyp(sp->stype, sp->sdf, sp->sap)) { case INTEGER: case SSE: if (typ == SSE) rno = XMM0 + nsse++; else rno = argregsi[ngpr++]; r = block(REG, NIL, NIL, sp->stype, sp->sdf, sp->sap); regno(r) = rno; p = tempnode(0, sp->stype, sp->sdf, sp->sap); sp->soffset = regno(p); sp->sflags |= STNODE; ecomp(buildtree(ASSIGN, p, r)); break; case SSEMEM: sp->soffset = nrsp; nrsp += SZDOUBLE; if (xtemps) { p = tempnode(0, sp->stype, sp->sdf, sp->sap); p = buildtree(ASSIGN, p, nametree(sp)); sp->soffset = regno(p->n_left); sp->sflags |= STNODE; ecomp(p); } break; case INTMEM: sp->soffset = nrsp; nrsp += SZLONG; if (xtemps) { p = tempnode(0, sp->stype, sp->sdf, sp->sap); p = buildtree(ASSIGN, p, nametree(sp)); sp->soffset = regno(p->n_left); sp->sflags |= STNODE; ecomp(p); } break; case STRMEM: /* Struct in memory */ sp->soffset = nrsp; nrsp += tsize(sp->stype, sp->sdf, sp->sap); break; case X87: /* long double args */ sp->soffset = nrsp; nrsp += SZLDOUBLE; break; case STRCPX: case STRREG: /* Struct in register */ /* Allocate space on stack for the struct */ /* For simplicity always fetch two longwords */ autooff += (2*SZLONG); if (typ == STRCPX) { t = DOUBLE; rno = XMM0 + nsse++; } else { t = LONG; rno = argregsi[ngpr++]; } r = block(REG, NIL, NIL, t, 0, MKAP(t)); regno(r) = rno; ecomp(movtomem(r, -autooff, FPREG)); if (tsize(sp->stype, sp->sdf, sp->sap) > SZLONG) { r = block(REG, NIL, NIL, t, 0, MKAP(t)); regno(r) = (typ == STRCPX ? XMM0 + nsse++ : argregsi[ngpr++]); ecomp(movtomem(r, -autooff+SZLONG, FPREG)); } sp->soffset = -autooff; break; default: cerror("bfcode: %d", typ); } } /* Check if there are varargs */ if (cftnsp->sdf == NULL || cftnsp->sdf->dfun == NULL) return; /* no prototype */ al = cftnsp->sdf->dfun; for (; al->type != TELLIPSIS; al++) { t = al->type; if (t == TNULL) return; if (BTYPE(t) == STRTY || BTYPE(t) == UNIONTY) al++; for (; t > BTMASK; t = DECREF(t)) if (ISARY(t) || ISFTN(t)) al++; } /* fix stack offset */ SETOFF(autooff, ALMAX); /* Save reg arguments in the reg save area */ p = NIL; for (i = ngpr; i < 6; i++) { r = block(REG, NIL, NIL, LONG, 0, MKAP(LONG)); regno(r) = argregsi[i]; r = movtomem(r, -RSALONGOFF(i)-autooff, FPREG); p = (p == NIL ? r : block(COMOP, p, r, INT, 0, MKAP(INT))); } for (i = nsse; i < 8; i++) { r = block(REG, NIL, NIL, DOUBLE, 0, MKAP(DOUBLE)); regno(r) = i + XMM0; r = movtomem(r, -RSADBLOFF(i)-autooff, FPREG); p = (p == NIL ? r : block(COMOP, p, r, INT, 0, MKAP(INT))); } autooff += RSASZ; rsaoff = autooff; thissse = nsse; thisgpr = ngpr; thisrsp = nrsp; ecomp(p); }
/* * does the type t match tword */ int ttype(TWORD t, int tword) { if (tword & TANY) return(1); #ifdef PCC_DEBUG if (t2debug) printf("ttype(0x%x, 0x%x)\n", t, tword); #endif if (ISPTR(t) && ISFTN(DECREF(t)) && (tword & TFTN)) { /* For funny function pointers */ return 1; } if (ISPTR(t) && (tword&TPTRTO)) { do { t = DECREF(t); } while (ISARY(t)); /* arrays that are left are usually only * in structure references... */ return (ttype(t, tword&(~TPTRTO))); } if (t != BTYPE(t)) return (tword & TPOINT); /* TPOINT means not simple! */ if (tword & TPTRTO) return(0); switch (t) { case CHAR: return( tword & TCHAR ); case SHORT: return( tword & TSHORT ); case STRTY: case UNIONTY: return( tword & TSTRUCT ); case INT: return( tword & TINT ); case UNSIGNED: return( tword & TUNSIGNED ); case USHORT: return( tword & TUSHORT ); case UCHAR: return( tword & TUCHAR ); case ULONG: return( tword & TULONG ); case LONG: return( tword & TLONG ); case LONGLONG: return( tword & TLONGLONG ); case ULONGLONG: return( tword & TULONGLONG ); case FLOAT: return( tword & TFLOAT ); case DOUBLE: return( tword & TDOUBLE ); case LDOUBLE: return( tword & TLDOUBLE ); } return(0); }
/* clocal() is called to do local transformations on * an expression tree preparitory to its being * written out in intermediate code. * * the major essential job is rewriting the * automatic variables and arguments in terms of * REG and OREG nodes * conversion ops which are not necessary are also clobbered here * in addition, any special features (such as rewriting * exclusive or) are easily handled here as well */ NODE * clocal(NODE *p) { register struct symtab *q; register NODE *r, *l; register int o; TWORD t; #ifdef PCC_DEBUG if (xdebug) { printf("clocal: %p\n", p); fwalk(p, eprint, 0); } #endif switch( o = p->n_op ){ case NAME: if ((q = p->n_sp) == NULL) return p; /* Nothing to care about */ switch (q->sclass) { case PARAM: case AUTO: /* fake up a structure reference */ r = block(REG, NIL, NIL, PTR+STRTY, 0, 0); slval(r, 0); r->n_rval = FPREG; p = stref(block(STREF, r, p, 0, 0, 0)); break; case REGISTER: p->n_op = REG; slval(p, 0); p->n_rval = q->soffset; break; case USTATIC: case STATIC: if (kflag == 0) break; if (blevel > 0 && !statinit) p = picstatic(p); break; case EXTERN: case EXTDEF: if (kflag == 0) break; if (blevel > 0 && !statinit) p = picext(p); break; } break; case ADDROF: if (kflag == 0 || blevel == 0 || statinit) break; /* char arrays may end up here */ l = p->n_left; if (l->n_op != NAME || (l->n_type != ARY+CHAR && l->n_type != ARY+WCHAR_TYPE)) break; l = p; p = picstatic(p->n_left); nfree(l); if (p->n_op != UMUL) cerror("ADDROF error"); l = p; p = p->n_left; nfree(l); break; case STASG: /* convert struct assignment to call memcpy */ l = p->n_left; if (l->n_op == NAME && ISFTN(l->n_sp->stype)) break; /* struct return, do nothing */ /* first construct arg list */ p->n_left = buildtree(ADDROF, p->n_left, 0); r = bcon(tsize(STRTY, p->n_df, p->n_ap)/SZCHAR); p->n_left = buildtree(CM, p->n_left, p->n_right); p->n_right = r; p->n_op = CM; p->n_type = INT; r = block(NAME, NIL, NIL, INT, 0, 0); r->n_sp = lookup(addname("memcpy"), SNORMAL); if (r->n_sp->sclass == SNULL) { r->n_sp->sclass = EXTERN; r->n_sp->stype = INCREF(VOID+PTR)+(FTN-PTR); } r->n_type = r->n_sp->stype; p = buildtree(CALL, r, p); break; case SCONV: l = p->n_left; if (l->n_op == ICON && ISPTR(l->n_type)) { /* Do immediate cast here */ /* Should be common code */ q = l->n_sp; l->n_sp = NULL; l->n_type = UNSIGNED; if (concast(l, p->n_type) == 0) cerror("clocal"); p = nfree(p); p->n_sp = q; } break; case FORCE: /* put return value in return reg */ p->n_op = ASSIGN; p->n_right = p->n_left; p->n_left = block(REG, NIL, NIL, p->n_type, 0, 0); t = p->n_type; if (ISITY(t)) t = t - (FIMAG-FLOAT); p->n_left->n_rval = RETREG(t); break; } #ifdef PCC_DEBUG if (xdebug) { printf("clocal end: %p\n", p); fwalk(p, eprint, 0); } #endif return(p); }
/* * Define everything needed to print out some data (or text). * This means segment, alignment, visibility, etc. */ void defloc(struct symtab *sp) { extern char *nextsect; static char *loctbl[] = { "text", "data", "section .rodata" }; extern int tbss; int weak = 0; char *name; TWORD t; int s; if (sp == NULL) { lastloc = -1; return; } if (kflag) { loctbl[DATA] = "section .data.rel.rw,\"aw\",@progbits"; loctbl[RDATA] = "section .data.rel.ro,\"aw\",@progbits"; } t = sp->stype; s = ISFTN(t) ? PROG : ISCON(cqual(t, sp->squal)) ? RDATA : DATA; if ((name = sp->soname) == NULL) name = exname(sp->sname); if (sp->sflags & STLS) { if (s != DATA) cerror("non-data symbol in tls section"); if (tbss) nextsect = ".tbss,\"awT\",@nobits"; else nextsect = ".tdata,\"awT\",@progbits"; tbss = 0; lastloc = -1; } #ifdef GCC_COMPAT { struct attr *ga; if ((ga = attr_find(sp->sap, GCC_ATYP_SECTION)) != NULL) nextsect = ga->sarg(0); if ((ga = attr_find(sp->sap, GCC_ATYP_WEAK)) != NULL) weak = 1; if (attr_find(sp->sap, GCC_ATYP_DESTRUCTOR)) { printf("\t.section\t.dtors,\"aw\",@progbits\n"); printf("\t.align 8\n\t.quad\t%s\n", name); lastloc = -1; } if (attr_find(sp->sap, GCC_ATYP_CONSTRUCTOR)) { printf("\t.section\t.ctors,\"aw\",@progbits\n"); printf("\t.align 8\n\t.quad\t%s\n", name); lastloc = -1; } if ((ga = attr_find(sp->sap, GCC_ATYP_VISIBILITY)) && strcmp(ga->sarg(0), "default")) printf("\t.%s %s\n", ga->sarg(0), name); } #endif if (nextsect) { printf(" .section %s\n", nextsect); nextsect = NULL; s = -1; } else if (s != lastloc) printf(" .%s\n", loctbl[s]); lastloc = s; while (ISARY(t)) t = DECREF(t); s = ISFTN(t) ? ALINT : talign(t, sp->sap); if (s > ALCHAR) printf(" .align %d\n", s/ALCHAR); if (weak) printf(" .weak %s\n", name); else if (sp->sclass == EXTDEF) { printf("\t.globl %s\n", name); printf("\t.type %s,@%s\n", name, ISFTN(t)? "function" : "object"); } if (sp->slevel == 0) printf("%s:\n", name); else printf(LABFMT ":\n", sp->soffset); }
/* * Define everything needed to print out some data (or text). * This means segment, alignment, visibility, etc. */ void defloc(struct symtab *sp) { extern char *nextsect; static char *loctbl[] = { "text", "data", "section .rodata" }; extern int tbss; char *name; TWORD t; int s; if (sp == NULL) { lastloc = -1; return; } if (kflag) { #ifdef MACHOABI loctbl[DATA] = "section .data.rel.rw,\"aw\""; loctbl[RDATA] = "section .data.rel.ro,\"aw\""; #else loctbl[DATA] = "section .data.rel.rw,\"aw\",@progbits"; loctbl[RDATA] = "section .data.rel.ro,\"aw\",@progbits"; #endif } t = sp->stype; s = ISFTN(t) ? PROG : ISCON(cqual(t, sp->squal)) ? RDATA : DATA; if ((name = sp->soname) == NULL) name = exname(sp->sname); if (sp->sflags & STLS) { if (s != DATA) cerror("non-data symbol in tls section"); if (tbss) nextsect = ".tbss,\"awT\",@nobits"; else nextsect = ".tdata,\"awT\",@progbits"; tbss = 0; lastloc = -1; } varattrib(name, sp->sap); if (nextsect) { printf(" .section %s\n", nextsect); nextsect = NULL; s = -1; } else if (s != lastloc) printf(" .%s\n", loctbl[s]); lastloc = s; while (ISARY(t)) t = DECREF(t); s = ISFTN(t) ? ALINT : talign(t, sp->sap); if (s > ALCHAR) printf(" .align %d\n", s/ALCHAR); if (sp->sclass == EXTDEF) { printf("\t.globl %s\n", name); #ifndef MACHOABI printf("\t.type %s,@%s\n", name, ISFTN(t)? "function" : "object"); #endif } if (sp->slevel == 0) printf("%s:\n", name); else printf(LABFMT ":\n", sp->soffset); }