add stuff

This commit is contained in:
sfja 2025-10-02 22:06:12 +02:00
parent 9eb3922ad6
commit ffd29ea5af
8 changed files with 314 additions and 4 deletions

View File

@ -52,6 +52,8 @@ jnz r/i16
cmp r/i16
mov r/i16/m r
mov r r/i16/m
movb m r
movb r m
in r/i16
out r/i16 r/i16
call r/i16

50
asm/hash.c Normal file
View File

@ -0,0 +1,50 @@
#include "hash.h"
#include <stddef.h>
#include <stdlib.h>
Hasher* hasher_new()
{
Hasher* hasher = malloc(sizeof(Hasher));
*hasher = (Hasher) {};
return hasher;
}
uint64_t hasher_finish(Hasher hasher)
{
return hasher.state;
}
void hasher_free(Hasher* hasher)
{
free(hasher);
}
void hasher_hash_u64(Hasher* hasher, uint64_t v)
{
uint64_t value = hasher->state + v;
value ^= value >> 33;
value *= 0xff51afd7ed558ccdL;
value ^= value >> 33;
value *= 0xc4ceb9fe1a85ec53L;
value ^= value >> 33;
hasher->state = value;
}
void hasher_hash_u8(Hasher* hasher, uint8_t v)
{
hasher_hash_u64(hasher, v);
}
void string_hash(Hasher* hasher, const char* str)
{
for (size_t i = 0; str[i] != '\0'; ++i) {
hasher_hash_u8(hasher, (uint8_t)str[i]);
}
}
void size_hash(Hasher* hasher, size_t value)
{
hasher_hash_u64(hasher, (uint64_t)value);
}

18
asm/hash.h Normal file
View File

@ -0,0 +1,18 @@
#ifndef HASH_H
#define HASH_H
#include <stddef.h>
#include <stdint.h>
typedef struct {
uint64_t state;
} Hasher;
uint64_t hasher_finish(Hasher hasher);
void hasher_hash_u64(Hasher* hasher, uint64_t v);
void hasher_hash_u8(Hasher* hasher, uint8_t v);
void string_hash(Hasher* hasher, const char* str);
void size_hash(Hasher* hasher, size_t value);
#endif

View File

@ -1,6 +1,10 @@
#include "hash.h"
#include "map.h"
#include "parse.h"
#include "report.h"
#include "vec.h"
#include <errno.h>
#include <stddef.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
@ -12,6 +16,15 @@ typedef struct {
static int parse_args(Args* args, int argc, char** argv);
DEFINE_VEC(LineVec, line_vec, PLine*)
typedef struct {
size_t line_idx;
char* ident;
} Label;
DEFINE_STRINGMAP(LabelMap, label_map, Label)
static char* read_text_file(const char* filename);
int main(int argc, char** argv)
@ -21,6 +34,8 @@ int main(int argc, char** argv)
return EXIT_FAILURE;
}
LabelMap labels = {};
char* text = read_text_file(args.input_file);
if (!text) {
return EXIT_FAILURE;
@ -28,9 +43,10 @@ int main(int argc, char** argv)
Parser* parser = parser_new(args.input_file, text);
size_t lines_capacity = 1024;
PLine** lines = malloc(sizeof(PLine*) * lines_capacity);
size_t lines_size = 0;
LineVec lines;
line_vec_construct(&lines);
Label* super_label = nullptr;
while (!parser_done(parser)) {
if (parser_next_is_const(parser)) {
@ -41,10 +57,52 @@ int main(int argc, char** argv)
} else {
PLabel* label;
while ((label = parser_parse_label(parser)) != nullptr) { }
while ((label = parser_parse_label(parser)) != nullptr) {
if (label->local) {
char* ident = calloc(1,
strlen(super_label->ident) + strlen(label->ident) + 2);
strcat(ident, super_label->ident);
strcat(ident, ".");
strcat(ident, label->ident);
label_map_set(&labels,
ident,
(Label) {
.line_idx = lines.size + 1,
.ident = ident,
});
} else {
label_map_set(&labels,
label->ident,
(Label) {
.line_idx = lines.size + 1,
.ident = strdup(label->ident),
});
super_label = label_map_at(&labels, label->ident);
}
plabel_free(label);
}
PLine* line = parser_parse_line(parser);
line_vec_push(&lines, line);
printf("ident = '%s'\n", line->ident);
}
}
parser_free(parser);
free(text);
for (size_t i = 0; i < lines.size; ++i) {
pline_free(lines.data[i]);
}
line_vec_destroy(&lines);
for (size_t i = 0; i < labels.entries.size; ++i) {
free(labels.entries.data[i].value.ident);
}
label_map_destroy(&labels);
return EXIT_SUCCESS;
}

106
asm/map.h Normal file
View File

@ -0,0 +1,106 @@
#ifndef MAP
#define MAP
#include "hash.h"
#include "vec.h"
#include <stddef.h>
#include <stdint.h>
#define DEFINE_MAP(TYPENAME, FN_PREFIX, KEY_TYPE, VALUE_TYPE, HASH_FN) \
\
typedef struct { \
uint64_t keyhash; \
VALUE_TYPE value; \
} _internal_TYPENAME##Entry; \
\
DEFINE_VEC(_internal_TYPENAME##EntryVec, \
_internal_##FN_PREFIX##_entryvec, \
_internal_TYPENAME##Entry) \
\
typedef struct { \
_internal_TYPENAME##EntryVec entries; \
} TYPENAME; \
\
[[maybe_unused]] static void FN_PREFIX##_construct(TYPENAME* map) \
{ \
*map = (TYPENAME) {}; \
} \
\
[[maybe_unused]] static void FN_PREFIX##_destroy(TYPENAME* map) \
{ \
_internal_##FN_PREFIX##_entryvec_destroy(&map->entries); \
} \
\
[[maybe_unused]] static bool _internal_##FN_PREFIX##_find_entry_idx( \
TYPENAME* map, \
size_t* target_idx, \
uint64_t keyhash, \
size_t begin, \
size_t end) \
{ \
if (begin == end) { \
*target_idx = begin; \
return false; \
} \
size_t middle_idx = (end - begin) / 2 + begin; \
_internal_TYPENAME##Entry* middle_entry \
= &map->entries.data[middle_idx]; \
if (keyhash < middle_entry->keyhash) { \
return _internal_##FN_PREFIX##_find_entry_idx( \
map, target_idx, keyhash, begin, middle_idx); \
} else if (keyhash > middle_entry->keyhash) { \
return _internal_##FN_PREFIX##_find_entry_idx( \
map, target_idx, keyhash, middle_idx + 1, end); \
} else { \
*target_idx = middle_idx; \
return true; \
} \
} \
\
[[maybe_unused]] static void FN_PREFIX##_set( \
TYPENAME* map, KEY_TYPE key, VALUE_TYPE value) \
{ \
Hasher hasher = {}; \
HASH_FN(&hasher, key); \
uint64_t keyhash = hasher_finish(hasher); \
\
size_t target_idx; \
bool exists = _internal_##FN_PREFIX##_find_entry_idx( \
map, &target_idx, keyhash, 0, map->entries.size); \
\
if (exists) { \
map->entries.data[target_idx].value = value; \
return; \
} \
\
_internal_##FN_PREFIX##_entryvec_push( \
&map->entries, (_internal_TYPENAME##Entry) {}); \
for (size_t i = map->entries.size - 1; i > target_idx; --i) { \
map->entries.data[i] = map->entries.data[i - 1]; \
} \
map->entries.data[target_idx] \
= (_internal_TYPENAME##Entry) { keyhash, value }; \
} \
\
[[maybe_unused]] static VALUE_TYPE* FN_PREFIX##_at( \
TYPENAME* map, KEY_TYPE key) \
{ \
Hasher hasher = {}; \
HASH_FN(&hasher, key); \
uint64_t keyhash = hasher_finish(hasher); \
\
size_t target_idx; \
bool exists = _internal_##FN_PREFIX##_find_entry_idx( \
map, &target_idx, keyhash, 0, map->entries.size); \
\
if (!exists) { \
return nullptr; \
} \
\
return &map->entries.data[target_idx].value; \
}
#define DEFINE_STRINGMAP(TYPENAME, FN_PREFIX, VALUE_TYPE) \
DEFINE_MAP(TYPENAME, FN_PREFIX, const char*, VALUE_TYPE, string_hash)
#endif

View File

@ -812,3 +812,31 @@ void pexpr_free(PExpr* expr)
}
free(expr);
}
void pconst_free(PConst* stmt)
{
free(stmt->ident);
pexpr_free(stmt->value);
free(stmt);
}
void pinclude_free(PInclude* stmt)
{
free(stmt->filename);
free(stmt);
}
void plabel_free(PLabel* stmt)
{
free(stmt->ident);
free(stmt);
}
void pline_free(PLine* stmt)
{
free(stmt->ident);
for (size_t i = 0; i < stmt->ops_size; ++i) {
pexpr_free(stmt->ops[i]);
}
free(stmt);
}

View File

@ -50,17 +50,23 @@ typedef struct {
PExpr* value;
} PConst;
void pconst_free(PConst* stmt);
typedef struct {
Loc loc;
char* filename;
} PInclude;
void pinclude_free(PInclude* stmt);
typedef struct {
Loc loc;
char* ident;
bool local;
} PLabel;
void plabel_free(PLabel* stmt);
typedef struct {
Loc loc;
char* ident;
@ -68,6 +74,8 @@ typedef struct {
size_t ops_size;
} PLine;
void pline_free(PLine* stmt);
typedef struct Parser Parser;
Parser* parser_new(const char* filename, const char* text);

40
asm/vec.h Normal file
View File

@ -0,0 +1,40 @@
#ifndef VEC_H
#define VEC_H
#include <stddef.h>
#include <stdlib.h>
#define DEFINE_VEC(TYPENAME, FN_PREFIX, TYPE) \
\
typedef struct { \
TYPE* data; \
size_t size; \
size_t capacity; \
} TYPENAME; \
\
[[maybe_unused]] static void FN_PREFIX##_construct(TYPENAME* vec) \
{ \
*vec = (TYPENAME) {}; \
} \
\
[[maybe_unused]] static void FN_PREFIX##_destroy(TYPENAME* vec) \
{ \
if (vec->data) { \
free(vec->data); \
} \
} \
\
[[maybe_unused]] static void FN_PREFIX##_push(TYPENAME* vec, TYPE value) \
{ \
if (!vec->data || vec->capacity == 0) { \
vec->capacity = 4; \
vec->data = malloc(sizeof(TYPE) * vec->capacity); \
} else if (vec->size + 1 >= vec->capacity) { \
vec->capacity *= 2; \
vec->data = realloc(vec->data, sizeof(TYPE) * vec->capacity); \
} \
vec->data[vec->size] = value; \
vec->size += 1; \
}
#endif