Files
ww/cmd/w6a/a.h
Hojun-Cho 4fe2e25da4 w6a: branch labels stay out of the symtab (isglobal wired)
Every interned symbol -- including branch labels defined via
p.label -- was emitted STB_GLOBAL, so labels were collide-able
across objects and the header's "GLOBAL symbols only" contract was
enforced nowhere (asym.isglobal was set but never read). Labels
stay interned for fixup resolution; the symtab now carries only
exported definitions, undefined externs, and reloc-referenced syms
(a reloc pre-pass marks those). rt/ensure.o drops from 15 emitted
syms to 2. Bootstrap 991-995 hold byte-identical on the new format.
2026-08-09 01:07:19 +09:00

112 lines
2.6 KiB
C

/*
* Modelled on Plan 9 cmd/6a/a.h, trimmed to the instruction subset
* that w6c emits. Line-oriented, no preprocessor: each non-blank,
* non-label line is one instruction.
*/
#ifndef SIX_A_H
#define SIX_A_H
#include "6.out.h"
#include <stddef.h>
#include <stdint.h>
#include <stdio.h>
typedef int8_t i8;
typedef int16_t i16;
typedef int32_t i32;
typedef int64_t i64;
typedef uint8_t u8;
typedef uint16_t u16;
typedef uint32_t u32;
typedef uint64_t u64;
typedef struct Aoperand Aoperand;
typedef struct Aprog Aprog;
typedef struct Asym Asym;
typedef struct Areloc Areloc;
typedef struct Asm Asm;
struct Aoperand {
int type; /* D_NONE, D_AX..D_R15, D_CONST, D_INDIR, D_EXTERN, D_BRANCH */
int reg; /* base register for D_INDIR */
i64 offset; /* immediate or displacement */
const char *sym;
};
struct Aprog {
int as; /* opcode (A_*) */
Aoperand from;
Aoperand to;
int line;
const char *label; /* label preceding this prog, if any */
Aprog *link;
/* for A_DATA: raw payload bytes interned by the parser */
u8 *bytes;
u64 nbytes;
};
struct Asym {
const char *name;
int defined; /* 1 if we own its address */
int is_text; /* if 1, address is in .text */
int is_data; /* if 1, address is in .data (mutually exclusive with is_text) */
int is_global; /* exported (TEXT/DATA/DATAW) */
int has_reloc; /* referenced by a relocation — must be in the symtab */
u64 addr; /* offset within section if defined */
int idx; /* ELF symtab index, filled at emit time */
Asym *next;
};
struct Areloc {
u64 off; /* offset within the relocation's section */
int section;/* 0 = .text (most relocs), 1 = .data (DATAR) */
int kind; /* R_X86_64_64 (1), R_X86_64_PC32 (2), R_X86_64_PLT32 (4) */
Asym *sym;
i64 addend;
Areloc *next;
};
struct Asm {
const char *file;
const char *src;
u64 srclen;
u64 pos;
int line;
Aprog *head, *tail;
u8 *text;
u64 textcap, textlen;
/* output data section (writable). Empty unless any DATAW directive
* was seen; in that case obj.c emits an extra .data PROGBITS
* section with SHF_WRITE. */
u8 *data;
u64 datacap, datalen;
Asym *syms;
Areloc *relocs;
int errs;
};
/* lex.c / parse.c */
void a_init(Asm*, const char *file, const char *src, u64 len);
int a_parse(Asm*);
/* asm.c */
int a_encode(Asm*);
/* obj.c */
int a_emit_elf(Asm*, FILE *out);
/* helpers */
Asym *a_intern(Asm*, const char *name);
void a_emit_byte(Asm*, u8);
void a_emit_u32(Asm*, u32);
void a_emit_data_byte(Asm*, u8);
void a_addreloc(Asm*, u64 off, int kind, Asym *s, i64 add);
void a_addreloc_data(Asm*, u64 off, int kind, Asym *s, i64 add);
#endif