#ifndef SYMTAB_H #define SYMTAB_H #include #include "limits.h" #include "riscv.h" #include "types.h" struct symbol_t; struct node_t; struct scope_t; struct type_t; /* Type classes for values. */ typedef enum { TYPE_VOID = 0, /* Special value for nodes without a type. */ TYPE_I8 = 1, /* Primitive types. */ TYPE_I16 = 2, TYPE_I32 = 3, TYPE_U8 = 4, TYPE_U16 = 5, TYPE_U32 = 6, TYPE_F32 = 7, TYPE_BOOL = 8, TYPE_FN = 9, /* Complex types. */ TYPE_UNION = 10, TYPE_RESULT = 11, TYPE_RECORD = 12, TYPE_ARRAY = 13, TYPE_PTR = 14, TYPE_SLICE = 15, TYPE_OPT = 16, TYPE_NEVER = 17, TYPE_OPAQUE = 18 } typeclass_t; typedef enum { SYM_ANY = 0, /* Match any symbol type */ SYM_VARIABLE, SYM_CONSTANT, /* Constant value */ SYM_FIELD, SYM_VARIANT, SYM_FUNCTION, SYM_TYPE, SYM_MODULE, } symkind_t; /* Symbol table scope. */ typedef struct scope_t { struct module_t *mod; struct scope_t *parent; struct symbol_t *symbols[MAX_SCOPE_SYMBOLS]; u16 nsymbols; } scope_t; /* Field, function or module attributes. */ typedef enum { ATTRIB_NONE = 0, ATTRIB_PUB = 1 << 0, ATTRIB_DEFAULT = 1 << 1, ATTRIB_EXTERN = 1 << 2, ATTRIB_TEST = 1 << 3, ATTRIB_INTRINSIC = 1 << 4, } attrib_t; /* Stack frame. */ typedef struct frame_t { i32 size; /* Maximum temporary stack usage (includes frame header). */ i32 sp; /* Temporary allocation cursor. */ } frame_t; /* Memory location for a value. */ typedef enum { LOC_NONE = 0, LOC_REG, LOC_STACK, LOC_IMM, LOC_ADDR } memloc_t; /* Offset from register, on stack. */ typedef struct { reg_t base; int offset; } offset_t; /* Address in memory with optional offset */ typedef struct { usize base; int offset; } addr_t; /* Immediates. */ typedef union { bool b; i32 i; u32 u; f32 f; } imm_t; /* Value handled by code generator. */ typedef struct value_t { struct type_t *type; memloc_t loc; bool temp; union { reg_t reg; /* Register. */ offset_t off; /* Offset from a base register. */ imm_t imm; /* Stored as an immediate. */ addr_t adr; /* Stored at a static address */ } as; } value_t; typedef struct symbol_t { const char *name; /* Symbol name. */ u16 length; /* Symbol name length. */ char qualified[MAX_QUALIFIED_NAME]; /* Fully qualified name */ struct node_t *node; /* Node defining the symbol. */ struct scope_t *scope; /* Scope where the symbol is defined */ symkind_t kind; /* Kind of symbol. */ union { struct { /* Variable entry. */ struct type_t *typ; /* Variable type. */ struct value_t val; /* Variable memory value. */ i32 align; /* Alignment override (bytes). */ } var; struct { struct type_t *typ; /* Variable type. */ i32 offset; /* Offset from start of object. */ } field; struct { struct type_t *typ; i32 tag; } variant; struct { /* Function entry. */ scope_t *scope; /* Inner scope. */ usize addr; /* Address in memory. */ frame_t frame; /* Stack frame information. */ attrib_t attribs; /* Attributes */ bool used; /* Whether function is called/used */ } fn; struct { /* Type entry. */ struct type_t *info; } typ; struct module_t *mod; /* Module entry. */ } e; } symbol_t; /* Allocate a symbol. */ symbol_t *alloc_symbol(symbol_t); /* Insert a symbol into a scope. */ bool symtab_insert(scope_t *s, const char *name, u16 length, struct node_t *n); /* Insert an identifier into a scope. */ bool symtab_add_ident(scope_t *s, struct node_t *ident, struct node_t *n); /* Add an imported symbol as an alias in the current scope. */ bool symtab_add_alias(scope_t *s, struct node_t *ident, symbol_t *original); /* Add a symbol directly to a scope. */ void symtab_add_symbol(scope_t *s, symbol_t *sym); /* Lookup a symbol in the given scope only. */ symbol_t *symtab_scope_lookup( scope_t *s, const char *name, u16 length, symkind_t kind ); /* Lookup a symbol in current and parent scopes. */ symbol_t *symtab_lookup( scope_t *s, const char *name, u16 length, symkind_t kind ); /* Create a new scope with the given parent. */ scope_t *symtab_scope(scope_t *parent, struct module_t *mod); #endif