summaryrefslogtreecommitdiff
path: root/src/cmd/5l/span.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/cmd/5l/span.c')
-rw-r--r--src/cmd/5l/span.c107
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;
}
}