Parcourir la source

More robust labels, implement symbol resolution.

master
Ben Kurtovic il y a 9 ans
Parent
révision
a7a3055325
6 fichiers modifiés avec 47 ajouts et 15 suppressions
  1. +28
    -7
      src/assembler.c
  2. +4
    -1
      src/assembler/errors.c
  3. +4
    -1
      src/assembler/errors.h
  4. +5
    -3
      src/assembler/preprocessor.c
  5. +3
    -1
      src/assembler/state.c
  6. +3
    -2
      src/assembler/state.h

+ 28
- 7
src/assembler.c Voir le fichier

@@ -14,8 +14,6 @@
#include "rom.h" #include "rom.h"
#include "util.h" #include "util.h"


#define IS_LABEL(line) (line->data[line->length - 1] == ':')

/* Sentinel values for overlap table */ /* Sentinel values for overlap table */
const ASMLine header_sentinel, bounds_sentinel; const ASMLine header_sentinel, bounds_sentinel;


@@ -34,7 +32,7 @@ static ErrorInfo* add_label_to_table(


const ASMSymbol *current = asm_symtable_find(symtable, symbol); const ASMSymbol *current = asm_symtable_find(symtable, symbol);
if (current) { if (current) {
ErrorInfo *ei = error_info_create(line, ET_LAYOUT, ED_LYT_DUPE_LABELS);
ErrorInfo *ei = error_info_create(line, ET_SYMBOL, ED_SYM_DUPE_LABELS);
error_info_append(ei, current->line); error_info_append(ei, current->line);
return ei; return ei;
} }
@@ -43,7 +41,8 @@ static ErrorInfo* add_label_to_table(
if (!label) if (!label)
OUT_OF_MEMORY() OUT_OF_MEMORY()


label->offset = offset;
// TODO: don't assume all ROM gets mapped to slot 2
label->offset = (offset >= 0xC000) ? ((offset & 0x3FFF) + 0x8000) : offset;
label->symbol = symbol; label->symbol = symbol;
label->line = line; label->line = line;
asm_symtable_insert(symtable, label); asm_symtable_insert(symtable, label);
@@ -144,7 +143,7 @@ static ErrorInfo* tokenize(AssemblerState *state)
overlap_table[state->header.offset + i] = &header_sentinel; overlap_table[state->header.offset + i] = &header_sentinel;


while (line) { while (line) {
if (IS_LABEL(line)) {
if (line->is_label) {
if ((ei = add_label_to_table(state->symtable, line, offset))) if ((ei = add_label_to_table(state->symtable, line, offset)))
goto cleanup; goto cleanup;
} }
@@ -261,9 +260,31 @@ static ErrorInfo* resolve_defaults(AssemblerState *state)
*/ */
static ErrorInfo* resolve_symbols(AssemblerState *state) static ErrorInfo* resolve_symbols(AssemblerState *state)
{ {
// TODO
ErrorInfo *ei;
ASMInstruction *inst = state->instructions;
const ASMSymbol *symbol;

while (inst) {
if (inst->symbol) {
symbol = asm_symtable_find(state->symtable, inst->symbol);
if (!symbol) {
ei = error_info_create(inst->line, ET_SYMBOL, ED_SYM_NO_LABEL);
return ei;
}


(void) state;
if (inst->loc.length == 3) {
inst->b2 = symbol->offset & 0xFF;
inst->b3 = symbol->offset >> 8;
} else {
inst->b3 = symbol->offset & 0xFF;
inst->b4 = symbol->offset >> 8;
}

free(inst->symbol);
inst->symbol = NULL;
}
inst = inst->next;
}
return NULL; return NULL;
} }




+ 4
- 1
src/assembler/errors.c Voir le fichier

@@ -17,6 +17,7 @@ static const char *asm_error_types[] = {
"include directive", // ET_INCLUDE "include directive", // ET_INCLUDE
"preprocessor", // ET_PREPROC "preprocessor", // ET_PREPROC
"memory layout", // ET_LAYOUT "memory layout", // ET_LAYOUT
"symbol table", // ET_SYMBOL
"instruction parser" // ET_PARSER "instruction parser" // ET_PARSER
}; };


@@ -33,11 +34,13 @@ static const char *asm_error_descs[] = {


"header offset exceeds given ROM size", // ED_LYT_HEADER_RANGE "header offset exceeds given ROM size", // ED_LYT_HEADER_RANGE
"declared ROM size in header exceeds actual size", // ED_LYT_DECLARE_RANGE "declared ROM size in header exceeds actual size", // ED_LYT_DECLARE_RANGE
"duplicate definitions for label", // ED_LYT_DUPE_LABELS
"location is out of bounds for the ROM size", // ED_LYT_BOUNDS "location is out of bounds for the ROM size", // ED_LYT_BOUNDS
"location overlaps with instruction or data", // ED_LYT_OVERLAP "location overlaps with instruction or data", // ED_LYT_OVERLAP
"location overlaps with ROM header", // ED_LYT_OVERLAP_HEAD "location overlaps with ROM header", // ED_LYT_OVERLAP_HEAD


"duplicate definitions for label", // ED_SYM_DUPE_LABELS
"undefined reference to label", // ED_SYM_NO_LABEL

"syntax error" // ED_PARSE_SYNTAX "syntax error" // ED_PARSE_SYNTAX
}; };




+ 4
- 1
src/assembler/errors.h Voir le fichier

@@ -13,6 +13,7 @@ typedef enum {
ET_INCLUDE, ET_INCLUDE,
ET_PREPROC, ET_PREPROC,
ET_LAYOUT, ET_LAYOUT,
ET_SYMBOL,
ET_PARSER ET_PARSER
} ASMErrorType; } ASMErrorType;


@@ -29,11 +30,13 @@ typedef enum {


ED_LYT_HEADER_RANGE, ED_LYT_HEADER_RANGE,
ED_LYT_DECLARE_RANGE, ED_LYT_DECLARE_RANGE,
ED_LYT_DUPE_LABELS,
ED_LYT_BOUNDS, ED_LYT_BOUNDS,
ED_LYT_OVERLAP, ED_LYT_OVERLAP,
ED_LYT_OVERLAP_HEAD, ED_LYT_OVERLAP_HEAD,


ED_SYM_DUPE_LABELS,
ED_SYM_NO_LABEL,

ED_PARSE_SYNTAX ED_PARSE_SYNTAX
} ASMErrorDesc; } ASMErrorDesc;




+ 5
- 3
src/assembler/preprocessor.c Voir le fichier

@@ -88,7 +88,7 @@
static inline bool is_valid_label_char(char c, bool first) static inline bool is_valid_label_char(char c, bool first)
{ {
return (c >= 'A' && c <= 'Z') || (c >= 'a' && c <= 'z') || return (c >= 'A' && c <= 'Z') || (c >= 'a' && c <= 'z') ||
(!first && c >= '0' && c <= '9') || c == '_';
(!first && c >= '0' && c <= '9') || c == '_' || c == '.';
} }


/* /*
@@ -125,6 +125,7 @@ static size_t read_labels(


strncpy(line->data, source + start, i - start + 1); strncpy(line->data, source + start, i - start + 1);
line->length = i - start + 1; line->length = i - start + 1;
line->is_label = true;


nexti = read_labels(source + i + 1, length - i - 1, &line->next, tail_ptr); nexti = read_labels(source + i + 1, length - i - 1, &line->next, tail_ptr);
*head_ptr = line; *head_ptr = line;
@@ -136,7 +137,7 @@ static size_t read_labels(
/* /*
Preprocess a single source line (source, length) into one or more ASMLines. Preprocess a single source line (source, length) into one or more ASMLines.


Only the data, length, and next fields of the ASMLine objects are
Only the data, length, is_label, and next fields of the ASMLine objects are
populated. The normalization process strips comments, makes various populated. The normalization process strips comments, makes various
adjustments outside of string literals (converts tabs to spaces, lowercases adjustments outside of string literals (converts tabs to spaces, lowercases
all alphabetical characters, and removes runs of multiple spaces), among all alphabetical characters, and removes runs of multiple spaces), among
@@ -209,6 +210,7 @@ static ASMLine* normalize_line(const char *source, size_t length)


line->data = data; line->data = data;
line->length = di; line->length = di;
line->is_label = false;
line->next = NULL; line->next = NULL;


if (head) { // Line has labels, so link the main part up if (head) { // Line has labels, so link the main part up
@@ -418,7 +420,7 @@ ErrorInfo* preprocess(AssemblerState *state, const LineBuffer *source)


while ((prev = line, line = next)) { while ((prev = line, line = next)) {
next = line->next; next = line->next;
if (line->data[0] != DIRECTIVE_MARKER)
if (line->is_label || line->data[0] != DIRECTIVE_MARKER)
continue; continue;
if (IS_LOCAL_DIRECTIVE(line)) if (IS_LOCAL_DIRECTIVE(line))
continue; // "Local" directives are handled by the tokenizer continue; // "Local" directives are handled by the tokenizer


+ 3
- 1
src/assembler/state.c Voir le fichier

@@ -144,7 +144,7 @@ static inline size_t hash_key(const char *key)
/* /*
Search for a key in the symbol table. Search for a key in the symbol table.


Return the key on success and NULL on failure.
Return the corresponding symbol on success and NULL on failure.
*/ */
const ASMSymbol* asm_symtable_find(const ASMSymbolTable *tab, const char *key) const ASMSymbol* asm_symtable_find(const ASMSymbolTable *tab, const char *key)
{ {
@@ -159,6 +159,8 @@ const ASMSymbol* asm_symtable_find(const ASMSymbolTable *tab, const char *key)


/* /*
Insert a symbol into the table. Insert a symbol into the table.

TODO: return boolean on success instead of void.
*/ */
void asm_symtable_insert(ASMSymbolTable *tab, ASMSymbol *symbol) void asm_symtable_insert(ASMSymbolTable *tab, ASMSymbol *symbol)
{ {


+ 3
- 2
src/assembler/state.h Voir le fichier

@@ -22,6 +22,7 @@ struct ASMLine {
size_t length; size_t length;
const Line *original; const Line *original;
const char *filename; const char *filename;
bool is_label;
struct ASMLine *next; struct ASMLine *next;
}; };
typedef struct ASMLine ASMLine; typedef struct ASMLine ASMLine;
@@ -40,8 +41,8 @@ typedef struct {
struct ASMInstruction { struct ASMInstruction {
ASMLocation loc; ASMLocation loc;
uint8_t b1, b2, b3, b4; uint8_t b1, b2, b3, b4;
uint8_t virtual_byte;
char *symbol; char *symbol;
const ASMLine *line;
struct ASMInstruction *next; struct ASMInstruction *next;
}; };
typedef struct ASMInstruction ASMInstruction; typedef struct ASMInstruction ASMInstruction;
@@ -54,7 +55,7 @@ struct ASMData {
typedef struct ASMData ASMData; typedef struct ASMData ASMData;


struct ASMSymbol { struct ASMSymbol {
size_t offset;
uint16_t offset;
char *symbol; char *symbol;
const ASMLine *line; const ASMLine *line;
struct ASMSymbol *next; struct ASMSymbol *next;


Chargement…
Annuler
Enregistrer