/* * 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); } }
/* * 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) { 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); }
/* * 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); }
static debug_type parse_coff_type (bfd *abfd, struct coff_symbols *symbols, struct coff_types *types, long coff_symno, int ntype, union internal_auxent *pauxent, bfd_boolean useaux, void *dhandle) { debug_type type; if ((ntype & ~N_BTMASK) != 0) { int newtype; newtype = DECREF (ntype); if (ISPTR (ntype)) { type = parse_coff_type (abfd, symbols, types, coff_symno, newtype, pauxent, useaux, dhandle); type = debug_make_pointer_type (dhandle, type); } else if (ISFCN (ntype)) { type = parse_coff_type (abfd, symbols, types, coff_symno, newtype, pauxent, useaux, dhandle); type = debug_make_function_type (dhandle, type, (debug_type *) NULL, FALSE); } else if (ISARY (ntype)) { int n; if (pauxent == NULL) n = 0; else { unsigned short *dim; int i; /* FIXME: If pauxent->x_sym.x_tagndx.l == 0, gdb sets the c_naux field of the syment to 0. */ /* Move the dimensions down, so that the next array picks up the next one. */ dim = pauxent->x_sym.x_fcnary.x_ary.x_dimen; n = dim[0]; for (i = 0; *dim != 0 && i < DIMNUM - 1; i++, dim++) *dim = *(dim + 1); *dim = 0; } type = parse_coff_type (abfd, symbols, types, coff_symno, newtype, pauxent, FALSE, dhandle); type = debug_make_array_type (dhandle, type, parse_coff_base_type (abfd, symbols, types, coff_symno, T_INT, NULL, dhandle), 0, n - 1, FALSE); } else { non_fatal (_("parse_coff_type: Bad type code 0x%x"), ntype); return DEBUG_TYPE_NULL; } return type; } if (pauxent != NULL && pauxent->x_sym.x_tagndx.l > 0) { debug_type *slot; /* This is a reference to an existing type. FIXME: gdb checks that the class is not C_STRTAG, nor C_UNTAG, nor C_ENTAG. */ slot = coff_get_slot (types, pauxent->x_sym.x_tagndx.l); if (*slot != DEBUG_TYPE_NULL) return *slot; else return debug_make_indirect_type (dhandle, slot, (const char *) NULL); } /* If the aux entry has already been used for something, useaux will have been set to false, indicating that parse_coff_base_type should not use it. We need to do it this way, rather than simply passing pauxent as NULL, because we need to be able handle multiple array dimensions while still discarding pauxent after having handled all of them. */ if (! useaux) pauxent = NULL; return parse_coff_base_type (abfd, symbols, types, coff_symno, ntype, pauxent, dhandle); }
/* * 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); }
/* * 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); }