selfhost/, cmd/, internal/ join the tree-wide sweep: every section banner dies (91 selfhost + the cmd C-style dividers -> 0); narration and stale contracts deleted (pre-#22 bundler notes, retired single-PT_LOAD and no-archive claims, superseded ABI tables); every ref/harec/qbe cite, task cite, encoding/ELF contract, and rule-10 twin pointer kept; lost lifetime/rationale lines restored where the sweep over-cut (elf_globals ownership, kwtab linear-scan). Comment- only proven: all five wwstage tool binaries byte-identical across the sweep; test-commit, test-byteid (161+1399, 0 pinned-divergent), and test-bootstrap (fixed point + 991-995 byte-id) all exit 0. The read-through banked 66 latent-bug leads (checkpoint).
111 lines
2.5 KiB
C
111 lines
2.5 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) */
|
|
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
|