w6a: DATAW directive for writable .data section
First step toward top-level mutable `let`. Adds a sibling directive to DATA whose bytes land in a separate writable .data PROGBITS section (SHF_ALLOC|SHF_WRITE, STT_OBJECT) instead of .text. The section is emitted only when DATAW was used, so inputs without it produce a byte-identical .o — tests 991 (selfhost .o diff) and 995 (self-rebuild) keep passing unchanged. w6l still treats data-resident syms as undefined; that's the next step.
This commit is contained in:
@@ -54,6 +54,17 @@ a_emit_u32(Asm *a, u32 v)
|
||||
a_emit_byte(a, (u8)((v >> 24) & 0xff));
|
||||
}
|
||||
|
||||
void
|
||||
a_emit_data_byte(Asm *a, u8 b)
|
||||
{
|
||||
if (a->datalen + 1 > a->datacap) {
|
||||
u64 nc = a->datacap ? a->datacap * 2 : 256;
|
||||
a->data = realloc(a->data, nc);
|
||||
a->datacap = nc;
|
||||
}
|
||||
a->data[a->datalen++] = b;
|
||||
}
|
||||
|
||||
void
|
||||
a_addreloc(Asm *a, u64 off, int kind, Asym *s, i64 add)
|
||||
{
|
||||
@@ -310,6 +321,20 @@ a_encode(Asm *a)
|
||||
a_emit_byte(a, p->bytes[i]);
|
||||
break;
|
||||
}
|
||||
case A_DATAW: {
|
||||
/* Writable variant: bytes go into .data (RW) instead
|
||||
* of .text. obj.c emits the extra section conditionally
|
||||
* on datalen > 0 so .o output stays byte-identical for
|
||||
* inputs that don't use DATAW. */
|
||||
Asym *s = a_intern(a, p->to.sym);
|
||||
s->defined = 1;
|
||||
s->is_data = 1;
|
||||
s->is_global = 1;
|
||||
s->addr = a->datalen;
|
||||
for (u64 i = 0; i < p->nbytes; i++)
|
||||
a_emit_data_byte(a, p->bytes[i]);
|
||||
break;
|
||||
}
|
||||
case A_RET:
|
||||
a_emit_byte(a, 0xC3);
|
||||
break;
|
||||
|
||||
Reference in New Issue
Block a user