/* * a.h — w6a-private header. Modelled on Plan 9 cmd/6a/a.h, trimmed * to the instruction subset that w6c emits. * * w6a is line-oriented and has no preprocessor: each non-blank, non- * label line is one instruction. We read the whole file into a list * of `Aprog`s, then encode and emit ELF64. */ #ifndef SIX_A_H #define SIX_A_H #include "6.out.h" #include #include #include 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) */ 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 { /* parser state */ const char *file; const char *src; u64 srclen; u64 pos; int line; /* program list */ Aprog *head, *tail; /* output text section */ 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; /* symbols */ 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