diff options
Diffstat (limited to 'src/cmd/5l/span.c')
-rw-r--r-- | src/cmd/5l/span.c | 107 |
1 files changed, 77 insertions, 30 deletions
diff --git a/src/cmd/5l/span.c b/src/cmd/5l/span.c index 13e1848e1..a5afa02e7 100644 --- a/src/cmd/5l/span.c +++ b/src/cmd/5l/span.c @@ -90,16 +90,36 @@ span(void) int32 c, otxt, out[6]; Section *sect; uchar *bp; + Sym *sub; if(debug['v']) Bprint(&bso, "%5.2f span\n", cputime()); Bflush(&bso); + sect = addsection(&segtext, ".text", 05); + lookup("text", 0)->sect = sect; + lookup("etext", 0)->sect = sect; + bflag = 0; c = INITTEXT; otxt = c; for(cursym = textp; cursym != nil; cursym = cursym->next) { + cursym->sect = sect; p = cursym->text; + if(p == P || p->link == P) { // handle external functions and ELF section symbols + if(cursym->type & SSUB) + continue; + if(cursym->align != 0) + c = rnd(c, cursym->align); + cursym->value = 0; + for(sub = cursym; sub != S; sub = sub->sub) { + sub->value += c; + for(p = sub->text; p != P; p = p->link) + p->pc += sub->value; + } + c += cursym->size; + continue; + } p->pc = c; cursym->value = c; @@ -160,6 +180,8 @@ span(void) bflag = 0; c = INITTEXT; for(cursym = textp; cursym != nil; cursym = cursym->next) { + if(!cursym->text || !cursym->text->link) + continue; cursym->value = c; for(p = cursym->text; p != P; p = p->link) { curp = p; @@ -217,6 +239,8 @@ span(void) */ for(cursym = textp; cursym != nil; cursym = cursym->next) { p = cursym->text; + if(p == P || p->link == P) + continue; autosize = p->to.offset + 4; symgrow(cursym, cursym->size); @@ -235,7 +259,6 @@ span(void) } } } - sect = addsection(&segtext, ".text", 05); sect->vaddr = INITTEXT; sect->len = c - INITTEXT; } @@ -269,12 +292,20 @@ flushpool(Prog *p, int skip, int force) q->to.type = D_BRANCH; q->cond = p->link; q->link = blitrl; + q->line = p->line; blitrl = q; } else if(!force && (p->pc+pool.size-pool.start < 2048)) return 0; elitrl->link = p->link; p->link = blitrl; + // BUG(minux): how to correctly handle line number for constant pool entries? + // for now, we set line number to the last instruction preceding them at least + // this won't bloat the .debug_line tables + while(blitrl) { + blitrl->line = p->line; + blitrl = blitrl->link; + } blitrl = 0; /* BUG: should refer back to values until out-of-range */ elitrl = 0; pool.size = 0; @@ -299,9 +330,11 @@ addpool(Prog *p, Adr *a) switch(c) { default: t.to = *a; + if(flag_shared && t.to.sym != S) + t.pcrel = p; break; - case C_SROREG: + case C_SROREG: case C_LOREG: case C_ROREG: case C_FOREG: @@ -316,11 +349,13 @@ addpool(Prog *p, Adr *a) break; } - for(q = blitrl; q != P; q = q->link) /* could hash on t.t0.offset */ - if(memcmp(&q->to, &t.to, sizeof(t.to)) == 0) { - p->cond = q; - return; - } + if(t.pcrel == P) { + for(q = blitrl; q != P; q = q->link) /* could hash on t.t0.offset */ + if(q->pcrel == P && memcmp(&q->to, &t.to, sizeof(t.to)) == 0) { + p->cond = q; + return; + } + } q = prg(); *q = t; @@ -407,25 +442,9 @@ immhalf(int32 v) int32 symaddr(Sym *s) { - int32 v; - - v = s->value; - switch(s->type) { - default: - diag("unexpected type %d in symaddr(%s)", s->type, s->name); - return 0; - - case STEXT: - case SELFROSECT: - case SRODATA: - case SDATA: - case SBSS: - case SCONST: - case SNOPTRDATA: - case SNOPTRBSS: - break; - } - return v; + if(!s->reachable) + diag("unreachable symbol in symaddr - %s", s->name); + return s->value; } int @@ -444,6 +463,9 @@ aclass(Adr *a) case D_REGREG: return C_REGREG; + case D_REGREG2: + return C_REGREG2; + case D_SHIFT: return C_SHIFT; @@ -552,7 +574,10 @@ aclass(Adr *a) if(s == S) break; instoffset = 0; // s.b. unused but just in case - return C_LCON; + if(flag_shared) + return C_LCONADDR; + else + return C_LCON; case D_AUTO: instoffset = autosize + a->offset; @@ -718,8 +743,14 @@ buildop(void) for(i=0; i<C_GOK; i++) for(n=0; n<C_GOK; n++) xcmp[i][n] = cmp(n, i); - for(n=0; optab[n].as != AXXX; n++) - ; + for(n=0; optab[n].as != AXXX; n++) { + if((optab[n].flag & LPCREL) != 0) { + if(flag_shared) + optab[n].size += optab[n].pcrelsiz; + else + optab[n].flag &= ~LPCREL; + } + } qsort(optab, n, sizeof(optab[0]), ocmp); for(i=0; i<n; i++) { r = optab[i].as; @@ -798,8 +829,11 @@ buildop(void) case AMOVM: case ARFE: case ATEXT: + case AUSEFIELD: + case ALOCALS: case ACASE: case ABCASE: + case ATYPE: break; case AADDF: oprange[AADDD] = oprange[r]; @@ -813,6 +847,8 @@ buildop(void) oprange[ASQRTD] = oprange[r]; oprange[AMOVFD] = oprange[r]; oprange[AMOVDF] = oprange[r]; + oprange[AABSF] = oprange[r]; + oprange[AABSD] = oprange[r]; break; case ACMPF: @@ -832,17 +868,28 @@ buildop(void) break; case AMULL: - oprange[AMULA] = oprange[r]; oprange[AMULAL] = oprange[r]; oprange[AMULLU] = oprange[r]; oprange[AMULALU] = oprange[r]; break; + case AMULWT: + oprange[AMULWB] = oprange[r]; + break; + + case AMULAWT: + oprange[AMULAWB] = oprange[r]; + break; + + case AMULA: case ALDREX: case ASTREX: case ALDREXD: case ASTREXD: case ATST: + case APLD: + case AUNDEF: + case ACLZ: break; } } |