add stuff
This commit is contained in:
parent
9eb3922ad6
commit
ffd29ea5af
@ -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
50
asm/hash.c
Normal 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
18
asm/hash.h
Normal 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
|
66
asm/main.c
66
asm/main.c
@ -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
106
asm/map.h
Normal 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
|
28
asm/parse.c
28
asm/parse.c
@ -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);
|
||||
}
|
||||
|
@ -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
40
asm/vec.h
Normal 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
|
Loading…
x
Reference in New Issue
Block a user