updated tlibc

This commit is contained in:
Timerix 2025-11-26 20:56:58 +05:00
parent 5397965319
commit cf724a8d13
19 changed files with 289 additions and 242 deletions

2
dependencies/tlibc vendored

@ -1 +1 @@
Subproject commit c415e2ca8ff51f41984ace8fe796187e6ad0fa27
Subproject commit 6a7f0a8715c54029ef71ce8152cd690815f950aa

View File

@ -1,17 +1,17 @@
#!/usr/bin/env bash
###########################################################
# Copy this file to your cbuild DEPENDENCY_CONFIGS_DIR #
# and enable it (ENABLED_DEPENDENCIES=tlibc). #
###########################################################
DEP_WORKING_DIR="dependencies/tlibc"
DEP_PRE_BUILD_COMMAND=""
DEP_POST_BUILD_COMMAND=""
# This is a dependency config.
# You can copy it to another project to add tlibc dependency.
DEP_WORKING_DIR="$DEPENDENCIES_DIR/tlibc"
if [[ "$TASK" = *_dbg ]]; then
dep_build_target="build_static_lib_dbg"
else
dep_build_target="build_static_lib"
fi
DEP_PRE_BUILD_COMMAND=""
DEP_BUILD_COMMAND="cbuild $dep_build_target"
DEP_POST_BUILD_COMMAND=""
DEP_CLEAN_COMMAND="cbuild clean"
DEP_DYNAMIC_OUT_FILES=""
DEP_STATIC_OUT_FILES="bin/tlibc.a"

View File

@ -1,13 +1,22 @@
#!/usr/bin/env bash
CBUILD_VERSION=2.2.3
CBUILD_VERSION=2.3.2
PROJECT="tcpu"
CMP_C="gcc"
CMP_CPP="g++"
STD_C="c11"
STD_C="c99"
STD_CPP="c++11"
WARN_C="-Wall -Wextra -Werror=return-type -Werror=pointer-arith -Wno-unused-parameter"
WARN_CPP="-Wall -Wextra -Werror=return-type -Werror=pointer-arith -Wno-unused-parameter"
WARN_C="-Wall -Wextra
-Wduplicated-branches
-Wduplicated-cond
-Wformat=2
-Wmissing-include-dirs
-Wshadow
-Werror=return-type
-Werror=pointer-arith
-Werror=init-self
-Werror=incompatible-pointer-types"
WARN_CPP="$WARN_C"
SRC_C="$(find src -name '*.c')"
SRC_CPP="$(find src -name '*.cpp')"
@ -24,9 +33,9 @@ ENABLED_DEPENDENCIES='tlibc'
# └── profile/ - gcc *.gcda profiling info files
OBJDIR="obj"
OUTDIR="bin"
STATIC_LIB_FILE="lib$PROJECT.a"
STATIC_LIB_FILE="$PROJECT.a"
INCLUDE="-Isrc -Idependencies/tlibc/include"
INCLUDE="-Isrc -I$DEPENDENCIES_DIR/tlibc/include"
# OS-specific options
case "$OS" in
@ -58,61 +67,61 @@ case "$TASK" in
C_ARGS="-O2 -flto=auto -fuse-linker-plugin -fprofile-use -fprofile-prefix-path=$(realpath $OBJDIR)/objects -fdata-sections -ffunction-sections -Wl,--gc-sections"
CPP_ARGS="$C_ARGS"
LINKER_ARGS="$CPP_ARGS $LINKER_LIBS"
PRE_TASK_SCRIPT=
TASK_SCRIPT=cbuild/default_tasks/build_exec.sh
POST_TASK_SCRIPT=
PRE_TASK_SCRIPT=""
TASK_SCRIPT="@cbuild/default_tasks/build_exec.sh"
POST_TASK_SCRIPT="@cbuild/default_tasks/strip_exec.sh"
;;
# creates executable with debug info and no optimizations
build_exec_dbg)
C_ARGS="-O0 -g3"
CPP_ARGS="$C_ARGS"
LINKER_ARGS="$CPP_ARGS $LINKER_LIBS"
PRE_TASK_SCRIPT=
TASK_SCRIPT=cbuild/default_tasks/build_exec.sh
POST_TASK_SCRIPT=
PRE_TASK_SCRIPT=""
TASK_SCRIPT="@cbuild/default_tasks/build_exec.sh"
POST_TASK_SCRIPT=""
;;
# creates shared library
build_shared_lib)
C_ARGS="-O2 -fpic -flto -shared"
CPP_ARGS="$C_ARGS"
LINKER_ARGS="$CPP_ARGS $LINKER_LIBS -Wl,-soname,$SHARED_LIB_FILE"
PRE_TASK_SCRIPT=
TASK_SCRIPT=cbuild/default_tasks/build_shared_lib.sh
POST_TASK_SCRIPT=
PRE_TASK_SCRIPT=""
TASK_SCRIPT="@cbuild/default_tasks/build_shared_lib.sh"
POST_TASK_SCRIPT=""
;;
# creates shared library with debug symbols and no optimizations
build_shared_lib_dbg)
C_ARGS="-O0 -g3 -fpic -shared"
CPP_ARGS="$C_ARGS"
LINKER_ARGS="$CPP_ARGS $LINKER_LIBS -Wl,-soname,$SHARED_LIB_FILE"
PRE_TASK_SCRIPT=
TASK_SCRIPT=cbuild/default_tasks/build_shared_lib.sh
POST_TASK_SCRIPT=
PRE_TASK_SCRIPT=""
TASK_SCRIPT="@cbuild/default_tasks/build_shared_lib.sh"
POST_TASK_SCRIPT=""
;;
# creates static library
build_static_lib)
C_ARGS="-O2 -fpic -fdata-sections -ffunction-sections"
CPP_ARGS="$C_ARGS"
PRE_TASK_SCRIPT=
TASK_SCRIPT=cbuild/default_tasks/build_static_lib.sh
POST_TASK_SCRIPT=
PRE_TASK_SCRIPT=""
TASK_SCRIPT="@cbuild/default_tasks/build_static_lib.sh"
POST_TASK_SCRIPT=""
;;
# creates static library with debug symbols and no optimizations
build_static_lib_dbg)
C_ARGS="-O0 -g3"
CPP_ARGS="$C_ARGS"
PRE_TASK_SCRIPT=
TASK_SCRIPT=cbuild/default_tasks/build_static_lib.sh
POST_TASK_SCRIPT=
PRE_TASK_SCRIPT=""
TASK_SCRIPT="@cbuild/default_tasks/build_static_lib.sh"
POST_TASK_SCRIPT=""
;;
# executes $EXEC_FILE
exec)
TASK_SCRIPT=cbuild/default_tasks/exec.sh
TASK_SCRIPT="@cbuild/default_tasks/exec.sh"
;;
# executes $EXEC_FILE with valgrind memory checker
valgrind)
VALGRIND_ARGS="-s --read-var-info=yes --track-origins=yes --fullpath-after=$(pwd) --leak-check=full --show-leak-kinds=all"
TASK_SCRIPT=cbuild/default_tasks/valgrind.sh
VALGRIND_ARGS="-s --read-var-info=yes --track-origins=yes --fullpath-after=$(pwd)/ --leak-check=full --show-leak-kinds=all"
TASK_SCRIPT="@cbuild/default_tasks/valgrind.sh"
;;
# generates profiling info
profile)
@ -126,22 +135,25 @@ case "$TASK" in
C_ARGS="-O2 -flto=auto -fuse-linker-plugin -fprofile-generate -fprofile-prefix-path=$(realpath $OBJDIR)/objects"
CPP_ARGS="$C_ARGS"
LINKER_ARGS="$CPP_ARGS $LINKER_LIBS"
PRE_TASK_SCRIPT=cbuild/default_tasks/build_exec.sh
TASK_SCRIPT=cbuild/default_tasks/profile.sh
POST_TASK_SCRIPT=
PRE_TASK_SCRIPT="@cbuild/default_tasks/build_exec.sh"
TASK_SCRIPT="@cbuild/default_tasks/profile.sh"
POST_TASK_SCRIPT=""
;;
# compiles program with -pg and runs it with gprof
# uses gprof2dot python script to generate function call tree (pip install gprof2dot)
# requires graphviz (https://www.graphviz.org/download/source/)
gprof)
OUTDIR="$OUTDIR/gprof"
# -pg adds code to executable, that generates file containing function call info (gmon.out)
C_ARGS="-O2 -flto=auto -fuse-linker-plugin -pg"
# arguments that emit some call counter code and disable optimizations to see function names
# https://github.com/msys2/MINGW-packages/issues/8503#issuecomment-1365475205
C_ARGS="-O0 -g -pg -no-pie -fno-omit-frame-pointer
-fno-inline-functions -fno-inline-functions-called-once
-fno-optimize-sibling-calls -fopenmp"
CPP_ARGS="$C_ARGS"
LINKER_ARGS="$CPP_ARGS $LINKER_LIBS"
PRE_TASK_SCRIPT=cbuild/default_tasks/build_exec.sh
TASK_SCRIPT=cbuild/default_tasks/gprof.sh
POST_TASK_SCRIPT=
PRE_TASK_SCRIPT="@cbuild/default_tasks/build_exec.sh"
TASK_SCRIPT="@cbuild/default_tasks/gprof.sh"
POST_TASK_SCRIPT=""
;;
# compiles program and runs it with callgrind (part of valgrind)
# uses gprof2dot python script to generate function call tree (pip install gprof2dot)
@ -153,9 +165,9 @@ case "$TASK" in
C_ARGS="-O2 -flto=auto -fuse-linker-plugin"
CPP_ARGS="$C_ARGS"
LINKER_ARGS="$CPP_ARGS $LINKER_LIBS"
PRE_TASK_SCRIPT=cbuild/default_tasks/build_exec.sh
TASK_SCRIPT=cbuild/default_tasks/callgrind.sh
POST_TASK_SCRIPT=
PRE_TASK_SCRIPT="@cbuild/default_tasks/build_exec.sh"
TASK_SCRIPT="@cbuild/default_tasks/callgrind.sh"
POST_TASK_SCRIPT=""
;;
# compiles executable with sanitizers and executes it to find errors and warnings
sanitize)
@ -163,19 +175,19 @@ case "$TASK" in
C_ARGS="-O0 -g3 -fsanitize=undefined,address"
CPP_ARGS="$C_ARGS"
LINKER_ARGS="$CPP_ARGS $LINKER_LIBS"
PRE_TASK_SCRIPT=cbuild/default_tasks/build_exec.sh
TASK_SCRIPT=cbuild/default_tasks/exec.sh
POST_TASK_SCRIPT=
PRE_TASK_SCRIPT="@cbuild/default_tasks/build_exec.sh"
TASK_SCRIPT="@cbuild/default_tasks/exec.sh"
POST_TASK_SCRIPT=""
;;
# rebuilds specified dependencies
# EXAMPLE: `cbuild rebuild_dependencies=libexample1,fonts`
# 'all' can be specified to rebuild all dependencies
rebuild_dependencies)
TASK_SCRIPT=cbuild/default_tasks/rebuild_dependencies.sh
TASK_SCRIPT="@cbuild/default_tasks/rebuild_dependencies.sh"
;;
# deletes generated files
clean)
TASK_SCRIPT=cbuild/default_tasks/clean.sh
TASK_SCRIPT="@cbuild/default_tasks/clean.sh"
;;
# nothing to do
"" | no_task)

View File

@ -0,0 +1,11 @@
#!/usr/bin/env bash
# Project user config is ignored by git.
# Here you can add variables that users might want to change
# on their local machine, without commiting to the repository.
# Directory where you install dependencies.
# Do not confuse with DEPENDENCY_CONFIGS_DIR
# Example:
# libexample source code is at `../libexample`, and dependency config
# that specifies how to build this lib is at `dependencies/libexample.config`
DEPENDENCIES_DIR="dependencies"

View File

@ -15,6 +15,8 @@ static Display _d = {0};
static cstr _title = "TCPU v" TCPU_VERSION_CSTR;
bool Display_init(i32 w, i32 h, DisplayFlags flags){
(void)flags;
_d.width = w;
_d.height = h;
_d.window = NULL;

View File

@ -12,7 +12,7 @@ void _VM_setError(VM* vm, cstr context, cstr format, ...){
sprintf(position_str, "[at 0x%x][", (u32)vm->current_pos);
char* real_format = strcat_malloc(position_str, context, "] ", format);
va_start(argv, format);
char* NULLABLE(buf) = vsprintf_malloc(256, real_format, argv);
char* NULLABLE(buf) = vsprintf_malloc(real_format, argv);
va_end(argv);
free(real_format);
if(buf == NULL){

View File

@ -1,5 +1,7 @@
#include "AST.h"
Array_declare(str);
static Array(str) _ArgumentType_str_array = ARRAY(str, {
STR("Unset"),
STR("Register"),
@ -10,40 +12,40 @@ static Array(str) _ArgumentType_str_array = ARRAY(str, {
});
str ArgumentType_toString(ArgumentType t){
if(t >= Array_len(&_ArgumentType_str_array, str))
if(t >= _ArgumentType_str_array.len)
return STR("!!ArgumentType INDEX_ERROR!!");
return ((str*)_ArgumentType_str_array.data)[t];
return _ArgumentType_str_array.data[t];
}
void Section_construct(Section* sec, str name){
sec->name = name;
sec->data_definitions_list = List_alloc(DataDefinition, 256);
sec->operations_list = List_alloc(Operation, 1024);
sec->data_definitions_list = List_DataDefinition_alloc(256);
sec->operations_list = List_Operation_alloc(1024);
}
void Section_destroy(Section* sec){
for(u32 i = 0; i < Array_len(&sec->data_definitions_list, DataDefinition); i++){
DataDefinition* dd = (DataDefinition*)sec->data_definitions_list.data + i;
free(dd->data_bytes.data);
for(u32 i = 0; i < sec->data_definitions_list.len; i++){
DataDefinition* dd = sec->data_definitions_list.data + i;
List_u8_destroy(&dd->data_bytes);
}
free(sec->data_definitions_list.data);
List_DataDefinition_destroy(&sec->data_definitions_list);
for(u32 i = 0; i < Array_len(&sec->operations_list, Operation); i++){
Operation* op = (Operation*)sec->operations_list.data + i;
free(op->args.data);
for(u32 i = 0; i < sec->operations_list.len; i++){
Operation* op = sec->operations_list.data + i;
List_Argument_destroy(&op->args);
}
free(sec->operations_list.data);
List_Operation_destroy(&sec->operations_list);
}
void AST_construct(AST* ast){
ast->sections = List_alloc(Section, 32);
ast->sections = List_Section_alloc(32);
}
void AST_destroy(AST* ast){
for(u32 i = 0; i != Array_len(&ast->sections, Section); i++){
Section_destroy((Section*)ast->sections.data + i);
for(u32 i = 0; i != ast->sections.len; i++){
Section_destroy(ast->sections.data + i);
}
free(ast->sections.data);
List_Section_destroy(&ast->sections);
}

View File

@ -4,6 +4,7 @@
#include "instructions/instructions.h"
#include "instructions/registers.h"
#include "tlibc/collections/List.h"
#include "tlibc/collections/List_impl/List_u8.h"
typedef enum ArgumentType {
ArgumentType_Unset,
@ -26,12 +27,16 @@ typedef struct Argument {
} value;
} Argument;
List_declare(Argument);
typedef struct Operation {
List(Argument) args;
Opcode opcode;
} Operation;
List_declare(Operation);
typedef struct DataDefinition {
str name;
@ -39,6 +44,8 @@ typedef struct DataDefinition {
u32 element_size;
} DataDefinition;
List_declare(DataDefinition);
typedef struct Section {
str name;
@ -46,6 +53,8 @@ typedef struct Section {
List(Operation) operations_list;
} Section;
List_declare(Section);
void Section_construct(Section* Section, str name);
void Section_destroy(Section* Section);

View File

@ -4,20 +4,20 @@ void CompiledSection_construct(CompiledSection* ptr, str name){
ptr->name = name;
ptr->next = NULL;
ptr->offset = 0;
ptr->const_data_props_list = List_construct(ConstDataProps, NULL, 0, 0);
ptr->named_refs = List_construct(NamedRef, NULL, 0, 0);
ptr->bytes = List_alloc(u8, 64);
ptr->const_data_props_list = List_ConstDataProps_construct(NULL, 0, 0);
ptr->named_refs = List_NamedRef_construct(NULL, 0, 0);
ptr->bytes = List_u8_alloc(128);
}
void CompiledSection_destroy(CompiledSection* ptr){
free(ptr->const_data_props_list.data);
free(ptr->named_refs.data);
free(ptr->bytes.data);
List_ConstDataProps_destroy(&ptr->const_data_props_list);
List_NamedRef_destroy(&ptr->named_refs);
List_u8_destroy(&ptr->bytes);
}
void BinaryObject_construct(BinaryObject* ptr){
ptr->comp_sec_list = List_alloc(CompiledSection, 64);
ptr->comp_sec_list = List_CompiledSection_alloc(64);
HashMap_construct(&ptr->comp_sec_i_map, u32, NULL);
HashMap_construct(&ptr->const_data_props_map, ConstDataProps, NULL);
ptr->main_sec = NULL;
@ -25,11 +25,11 @@ void BinaryObject_construct(BinaryObject* ptr){
}
void BinaryObject_destroy(BinaryObject* ptr){
for(u32 i = 0; i < List_len(&ptr->comp_sec_list, CompiledSection); i++){
CompiledSection* sec_ptr = (CompiledSection*)ptr->comp_sec_list.data + i;
for(u32 i = 0; i < ptr->comp_sec_list.len; i++){
CompiledSection* sec_ptr = ptr->comp_sec_list.data + i;
CompiledSection_destroy(sec_ptr);
}
free(ptr->comp_sec_list.data);
List_CompiledSection_destroy(&ptr->comp_sec_list);
HashMap_destroy(&ptr->comp_sec_i_map);
HashMap_destroy(&ptr->const_data_props_map);

View File

@ -4,6 +4,7 @@
#include "instructions/instructions.h"
#include "instructions/registers.h"
#include "tlibc/collections/List.h"
#include "tlibc/collections/List_impl/List_u8.h"
#include "tlibc/collections/HashMap.h"
#include "AST.h"
@ -14,6 +15,8 @@ typedef struct ConstDataProps {
u32 offset; // offset in bytes from section start
} ConstDataProps;
List_declare(ConstDataProps)
#define ConstDataProps_construct(NAME, SIZE, OFFSET) ((ConstDataProps){ .name = NAME, .size = SIZE, .offset = OFFSET})
@ -29,6 +32,8 @@ typedef struct NamedRef {
u32 offset; // offset in bytes from section start
} NamedRef;
List_declare(NamedRef);
#define NamedRef_construct(NAME, TYPE, OFFSET) ((NamedRef){ .name = NAME, .type = TYPE, .offset = OFFSET})
@ -41,6 +46,8 @@ typedef struct CompiledSection {
List(u8) bytes;
} CompiledSection;
List_declare(CompiledSection)
void CompiledSection_construct(CompiledSection* ptr, str name);
void CompiledSection_destroy(CompiledSection* ptr);

View File

@ -3,27 +3,27 @@
void Compiler_construct(Compiler* cmp){
memset(cmp, 0, sizeof(Compiler));
cmp->state = CompilerState_Initial;
cmp->tokens = List_alloc(Token, 4096);
cmp->line_lengths = List_alloc(u32, 1024);
cmp->tokens = List_Token_alloc(4096);
cmp->line_lengths = List_u32_alloc(1024);
AST_construct(&cmp->ast);
BinaryObject_construct(&cmp->binary);
}
void Compiler_destroy(Compiler* cmp){
free(cmp->code.data);
free(cmp->tokens.data);
free(cmp->line_lengths.data);
str_destroy(cmp->code);
List_Token_destroy(&cmp->tokens);
List_u32_destroy(&cmp->line_lengths);
AST_destroy(&cmp->ast);
BinaryObject_destroy(&cmp->binary);
}
CodePos Compiler_getLineAndColumn(Compiler* cmp, u32 pos){
u32 prev_lines_len = 0;
if(pos >= cmp->code.size)
if(pos >= cmp->code.len)
return CodePos_create(0, 0);
for(u32 i = 0; i < List_len(&cmp->line_lengths, u32); i++){
u32 line_len = ((u32*)cmp->line_lengths.data)[i];
for(u32 i = 0; i < cmp->line_lengths.len; i++){
u32 line_len = cmp->line_lengths.data[i];
if(prev_lines_len + line_len > pos)
return CodePos_create(i + 1, pos + 1 - prev_lines_len);
prev_lines_len += line_len;
@ -34,15 +34,15 @@ CodePos Compiler_getLineAndColumn(Compiler* cmp, u32 pos){
void _Compiler_setError(Compiler* cmp, cstr context, cstr format, ...){
// happens at the end of file
if(cmp->pos >= cmp->code.size)
cmp->pos = cmp->code.size - 1;
if(cmp->pos >= cmp->code.len)
cmp->pos = cmp->code.len - 1;
char position_str[32];
CodePos code_pos = Compiler_getLineAndColumn(cmp, cmp->pos);
sprintf(position_str, "[at %u:%u][", code_pos.line, code_pos.column);
char* real_format = strcat_malloc(position_str, context, "] ", format);
va_list argv;
va_start(argv, format);
char* NULLABLE(buf) = vsprintf_malloc(512, real_format, argv);
char* NULLABLE(buf) = vsprintf_malloc(real_format, argv);
va_end(argv);
free(real_format);
if(buf == NULL){
@ -62,21 +62,24 @@ str Compiler_constructTokenStr(Compiler* cmp, Token t){
return s;
}
#define List_u8_pushStruct(L_PTR, S_PTR) List_u8_pushMany((L_PTR), (void*)(S_PTR), sizeof(*(S_PTR)))
static bool compileSection(Compiler* cmp, Section* sec){
u32 cs_index = List_len(&cmp->binary.comp_sec_list, CompiledSection);
CompiledSection* cs = List_expand_size(&cmp->binary.comp_sec_list, sizeof(CompiledSection));
u32 cs_index = cmp->binary.comp_sec_list.len;
CompiledSection* cs = List_CompiledSection_expand(&cmp->binary.comp_sec_list, 1);
CompiledSection_construct(cs, sec->name);
if(!HashMap_tryPush(&cmp->binary.comp_sec_i_map, cs->name, &cs_index)){
returnError("duplicate section '%s'", str_copy(sec->name).data);
}
// compile code
u8 zeroes[8] = {0, 0, 0, 0, 0, 0, 0, 0};
for(u32 i = 0; i < List_len(&sec->operations_list, Operation); i++){
Operation* op = (Operation*)sec->operations_list.data + i;
List_pushMany(&cs->bytes, u8, &op->opcode, sizeof(op->opcode));
for(u32 j = 0; j < List_len(&op->args, Argument); j++){
Argument* arg = (Argument*)op->args.data + j;
u8 zeroes_8[8];
memset(zeroes_8, 0, sizeof(zeroes_8));
for(u32 i = 0; i < sec->operations_list.len; i++){
Operation* op = sec->operations_list.data + i;
List_u8_pushStruct(&cs->bytes, &op->opcode);
for(u32 j = 0; j < op->args.len; j++){
Argument* arg = op->args.data + j;
switch(arg->type){
case ArgumentType_VarDataName:
returnError("argument type 'VarDataName' is not supported yet");
@ -86,35 +89,41 @@ static bool compileSection(Compiler* cmp, Section* sec){
returnError("invalid ArgumentType %i", arg->type);
case ArgumentType_Register:
List_push(&cs->bytes, u8, arg->value.register_code);
List_u8_push(&cs->bytes, arg->value.register_code);
break;
case ArgumentType_ConstValue:
List_pushMany(&cs->bytes, u8, &arg->value.i, 8);
List_u8_pushStruct(&cs->bytes, &arg->value.i);
break;
case ArgumentType_ConstDataPointer:
List_push(&cs->named_refs, NamedRef, NamedRef_construct(
List_NamedRef_push(&cs->named_refs,
NamedRef_construct(
arg->value.data_name,
NamedRefType_Ptr,
cs->bytes.size));
List_pushMany(&cs->bytes, u8, zeroes, 8);
cs->bytes.len
)
);
List_u8_pushStruct(&cs->bytes, zeroes_8);
break;
case ArgumentType_ConstDataSize:
List_push(&cs->named_refs, NamedRef, NamedRef_construct(
List_NamedRef_push(&cs->named_refs,
NamedRef_construct(
arg->value.data_name,
NamedRefType_Size,
cs->bytes.size));
List_pushMany(&cs->bytes, u8, zeroes, 8);
cs->bytes.len
)
);
List_u8_pushStruct(&cs->bytes, zeroes_8);
break;
}
}
}
// compile data
for(u32 i = 0; i < List_len(&sec->data_definitions_list, DataDefinition); i++){
DataDefinition* dd = (DataDefinition*)sec->data_definitions_list.data + i;
List_push(&cs->const_data_props_list, ConstDataProps,
ConstDataProps_construct(dd->name, dd->data_bytes.size, cs->bytes.size));
List_pushMany(&cs->bytes, u8, dd->data_bytes.data, dd->data_bytes.size);
for(u32 i = 0; i < sec->data_definitions_list.len; i++){
DataDefinition* dd = sec->data_definitions_list.data + i;
ConstDataProps cd_props = ConstDataProps_construct(dd->name, dd->data_bytes.len, cs->bytes.len);
List_ConstDataProps_push(&cs->const_data_props_list, cd_props);
List_u8_pushMany(&cs->bytes, dd->data_bytes.data, dd->data_bytes.len);
}
// TODO: push padding
@ -126,8 +135,8 @@ static bool compileBinary(Compiler* cmp){
returnErrorIf_auto(cmp->state != CompilerState_Parsing);
cmp->state = CompilerState_Compiling;
for(u32 i = 0; i < List_len(&cmp->ast.sections, Section); i++){
Section* sec = (Section*)cmp->ast.sections.data + i;
for(u32 i = 0; i < cmp->ast.sections.len; i++){
Section* sec = cmp->ast.sections.data + i;
if(!compileSection(cmp, sec)){
return false;
}
@ -140,25 +149,25 @@ static bool compileBinary(Compiler* cmp){
returnError("no 'main' section was defined");
}
u32 main_sec_i = *main_sec_i_ptr;
cmp->binary.main_sec = (CompiledSection*)cmp->binary.comp_sec_list.data + main_sec_i;
cmp->binary.main_sec = cmp->binary.comp_sec_list.data + main_sec_i;
// create linked list of CompiledSection where main is the first
CompiledSection* prev_sec = cmp->binary.main_sec;
u32 total_size = 0;
for(u32 i = 0; i < List_len(&cmp->binary.comp_sec_list, CompiledSection); i++){
CompiledSection* sec = (CompiledSection*)cmp->binary.comp_sec_list.data + i;
total_size += sec->bytes.size;
for(u32 i = 0; i < cmp->binary.comp_sec_list.len; i++){
CompiledSection* sec = cmp->binary.comp_sec_list.data + i;
total_size += sec->bytes.len;
bool is_main_sec = str_equals(sec->name, main_sec_name);
if(!is_main_sec){
sec->offset = prev_sec->offset + prev_sec->bytes.size;
sec->offset = prev_sec->offset + prev_sec->bytes.len;
}
ConstDataProps cd = ConstDataProps_construct(sec->name, sec->bytes.size, sec->offset);
ConstDataProps cd = ConstDataProps_construct(sec->name, sec->bytes.len, sec->offset);
if(!HashMap_tryPush(&cmp->binary.const_data_props_map, cd.name, &cd)){
returnError("duplicate named data '%s'", str_copy(cd.name).data);
}
for(u32 j = 0; j < List_len(&sec->const_data_props_list, ConstDataProps); j++){
cd = ((ConstDataProps*)sec->const_data_props_list.data)[j];
for(u32 j = 0; j < sec->const_data_props_list.len; j++){
cd = sec->const_data_props_list.data[j];
cd.offset += sec->offset;
if(!HashMap_tryPush(&cmp->binary.const_data_props_map, cd.name, &cd)){
returnError("duplicate named data '%s'", str_copy(cd.name).data);
@ -172,10 +181,10 @@ static bool compileBinary(Compiler* cmp){
}
// insert calculated offsets into sections
for(u32 i = 0; i < List_len(&cmp->binary.comp_sec_list, CompiledSection); i++){
CompiledSection* sec = (CompiledSection*)cmp->binary.comp_sec_list.data + i;
for(u32 j = 0; j < List_len(&sec->named_refs, NamedRef); j++){
NamedRef* ref = (NamedRef*)sec->named_refs.data +j;
for(u32 i = 0; i < cmp->binary.comp_sec_list.len; i++){
CompiledSection* sec = cmp->binary.comp_sec_list.data + i;
for(u32 j = 0; j < sec->named_refs.len; j++){
NamedRef* ref = sec->named_refs.data + j;
ConstDataProps* target_data = HashMap_tryGetPtr(
&cmp->binary.const_data_props_map, ref->name);
@ -206,7 +215,7 @@ static bool writeBinaryFile(Compiler* cmp, FILE* f){
CompiledSection* sec = cmp->binary.main_sec;
while(sec){
fwrite(sec->bytes.data, 1, sec->bytes.size, f);
fwrite(sec->bytes.data, 1, sec->bytes.len, f);
fflush(f);
sec = sec->next;
}
@ -232,7 +241,7 @@ bool Compiler_compile(Compiler* cmp, cstr source_file_name, cstr out_file_name,
}
fclose(f);
if(sb.buffer.size == 0){
if(sb.buffer.len == 0){
StringBuilder_destroy(&sb);
returnError("soucre file is empty");
}
@ -257,13 +266,13 @@ bool Compiler_compile(Compiler* cmp, cstr source_file_name, cstr out_file_name,
if(debug_log){
printf("------------------------------------[lines]------------------------------------\n");
for(u32 i = 0; i < List_len(&cmp->line_lengths, u32); i++){
printf("[%u] length: %u\n", i+1, ((u32*)cmp->line_lengths.data)[i]);
for(u32 i = 0; i < cmp->line_lengths.len; i++){
printf("[%u] length: %u\n", i+1, cmp->line_lengths.data[i]);
}
printf("------------------------------------[tokens]-----------------------------------\n");
for(u32 i = 0; i < List_len(&cmp->tokens, Token); i++){
Token t = ((Token*)cmp->tokens.data)[i];
for(u32 i = 0; i < cmp->tokens.len; i++){
Token t = cmp->tokens.data[i];
CodePos pos = Compiler_getLineAndColumn(cmp, t.begin);
char* tokstr = malloc(4096);
strncpy(tokstr, cmp->code.data + t.begin, t.length);
@ -290,23 +299,21 @@ bool Compiler_compile(Compiler* cmp, cstr source_file_name, cstr out_file_name,
if (debug_log){
printf("-------------------------------------[AST]-------------------------------------\n");
for(u32 i = 0; i < List_len(&cmp->ast.sections, Section); i++){
Section* sec = (Section*)cmp->ast.sections.data + i;
str tmpstr = str_copy(sec->name);
printf("section '%s'\n", tmpstr.data);
free(tmpstr.data);
for(u32 i = 0; i < cmp->ast.sections.len; i++){
Section* sec = cmp->ast.sections.data + i;
printf("section '"FMT_str"'\n", sec->name.len, sec->name.data);
for(u32 j = 0; j < List_len(&sec->data_definitions_list, DataDefinition); j++){
DataDefinition* dd = (DataDefinition*)sec->data_definitions_list.data + j;
tmpstr = str_copy(dd->name);
printf(" const%u %s (len %u)\n", dd->element_size * 8, tmpstr.data,
dd->data_bytes.size/dd->element_size);
free(tmpstr.data);
for(u32 j = 0; j < sec->data_definitions_list.len; j++){
DataDefinition* dd = sec->data_definitions_list.data + j;
printf(" const%u "FMT_str" (len %u)\n",
dd->element_size * 8,
dd->name.len, dd->name.data,
dd->data_bytes.len/dd->element_size);
}
for(u32 j = 0; j < List_len(&sec->operations_list, Operation); j++){
Operation* op = (Operation*)sec->operations_list.data + j;
for(u32 j = 0; j < sec->operations_list.len; j++){
Operation* op = sec->operations_list.data + j;
const Instruction* instr = Instruction_getByOpcode(op->opcode);
if(instr == NULL){
fclose(f);
@ -314,8 +321,8 @@ bool Compiler_compile(Compiler* cmp, cstr source_file_name, cstr out_file_name,
}
printf(" %s", instr->name.data);
for(u32 k = 0; k < List_len(&op->args, Argument); k++){
Argument* arg = (Argument*)op->args.data + k;
for(u32 k = 0; k < op->args.len; k++){
Argument* arg = op->args.data + k;
printf(" %s(", ArgumentType_toString(arg->type).data);
switch(arg->type){
@ -325,25 +332,19 @@ bool Compiler_compile(Compiler* cmp, cstr source_file_name, cstr out_file_name,
case ArgumentType_Register:;
str register_name = RegisterCode_toString(arg->value.register_code);
printf("%s 0x%x", register_name.data, arg->value.register_code);
free(register_name.data);
str_destroy(register_name);
break;
case ArgumentType_ConstValue:
printf(IFWIN("%lli", "%li"), arg->value.i);
break;
case ArgumentType_ConstDataPointer:
tmpstr = str_copy(arg->value.data_name);
printf("@%s", tmpstr.data);
free(tmpstr.data);
printf("@"FMT_str, arg->value.data_name.len, arg->value.data_name.data);
break;
case ArgumentType_ConstDataSize:
tmpstr = str_copy(arg->value.data_name);
printf("#%s", tmpstr.data);
free(tmpstr.data);
printf("#"FMT_str, arg->value.data_name.len, arg->value.data_name.data);
break;
case ArgumentType_VarDataName:
tmpstr = str_copy(arg->value.data_name);
printf("%s", tmpstr.data);
free(tmpstr.data);
printf(FMT_str, arg->value.data_name.len, arg->value.data_name.data);
break;
}
@ -365,11 +366,10 @@ bool Compiler_compile(Compiler* cmp, cstr source_file_name, cstr out_file_name,
success = compileBinary(cmp);
if(debug_log){
for(u32 i = 0; i < List_len(&cmp->binary.comp_sec_list, CompiledSection); i++){
CompiledSection* sec = (CompiledSection*)cmp->binary.comp_sec_list.data + i;
str tmpstr = str_copy(sec->name);
printf("compiled section '%s' to %u bytes with offset 0x%x\n", tmpstr.data, sec->bytes.size, sec->offset);
free(tmpstr.data);
for(u32 i = 0; i < cmp->binary.comp_sec_list.len; i++){
CompiledSection* sec = cmp->binary.comp_sec_list.data + i;
printf("compiled section '"FMT_str"' to %u bytes with offset 0x%x\n",
sec->name.len, sec->name.data, sec->bytes.len, sec->offset);
}
}

View File

@ -2,6 +2,7 @@
#include "tlibc/std.h"
#include "tlibc/string/str.h"
#include "tlibc/collections/List.h"
#include "tlibc/collections/List_impl/List_u32.h"
#include "tlibc/collections/HashMap.h"
#include "Token.h"
#include "Binary.h"

View File

@ -9,7 +9,7 @@
#define Error_endOfFile "unexpected end of file"
static void completeLine(Compiler* cmp){
List_push(&cmp->line_lengths, u32, cmp->column);
List_u32_push(&cmp->line_lengths, cmp->column);
cmp->column = 0;
}
@ -19,12 +19,12 @@ static void readCommentSingleLine(Compiler* cmp){
cmp->column++;
cmp->pos++;
while(cmp->pos < cmp->code.size){
while(cmp->pos < cmp->code.len){
c = cmp->code.data[cmp->pos];
// end of line
if(c == '\r' || c == '\n'){
tok.length = cmp->pos - tok.begin;
List_push(&cmp->tokens, Token, tok);
List_Token_push(&cmp->tokens, tok);
// cmp->line will be increased in lex()
return;
}
@ -35,7 +35,7 @@ static void readCommentSingleLine(Compiler* cmp){
// end of file
tok.length = cmp->pos - tok.begin;
List_push(&cmp->tokens, Token, tok);
List_Token_push(&cmp->tokens, tok);
}
static void readCommentMultiLine(Compiler* cmp){
@ -44,12 +44,12 @@ static void readCommentMultiLine(Compiler* cmp){
cmp->column++;
cmp->pos++;
while(cmp->pos < cmp->code.size){
while(cmp->pos < cmp->code.len){
c = cmp->code.data[cmp->pos];
// closing comment
if(cmp->pos > tok.begin + 3 && c == '/' && cmp->code.data[cmp->pos - 1] == '*') {
tok.length = cmp->pos - tok.begin + 1;
List_push(&cmp->tokens, Token, tok);
List_Token_push(&cmp->tokens, tok);
return;
}
@ -65,7 +65,7 @@ static void readCommentMultiLine(Compiler* cmp){
static void readComment(Compiler* cmp){
char c; // '/'
if(cmp->pos + 1 == cmp->code.size){
if(cmp->pos + 1 == cmp->code.len){
setError(Error_endOfFile);
return;
}
@ -91,19 +91,19 @@ static void readLabel(Compiler* cmp){
cmp->column++;
Token tok = Token_construct(TokenType_Label, cmp->pos, 0);
while(cmp->pos < cmp->code.size){
while(cmp->pos < cmp->code.len){
c = cmp->code.data[cmp->pos];
// end of line
if(c == ':' || c == '\r' || c == '\n'){
tok.length = cmp->pos - tok.begin;
if(tok.length > 0)
List_push(&cmp->tokens, Token, tok);
List_Token_push(&cmp->tokens, tok);
else setError(Error_unexpectedCharacter(cmp->code.data[--cmp->pos]));
// cmp->line will be increased in lex()
return;
}
if(!isAlphabeticalLower(c) && !isAlphabeticalUpper(c) && !isDigit(c) &&
if(!char_isLatinLower(c) && !char_isLatinUpper(c) && !char_isDigit(c) &&
c != '_' && c != '.'){
setError(Error_unexpectedCharacter(c));
return;
@ -116,7 +116,7 @@ static void readLabel(Compiler* cmp){
// end of file
tok.length = cmp->pos - tok.begin;
if(tok.length > 0)
List_push(&cmp->tokens, Token, tok);
List_Token_push(&cmp->tokens, tok);
else setError(Error_endOfFile);
}
@ -125,7 +125,7 @@ static void readArguments(Compiler* cmp){
Token tok = Token_construct(TokenType_Unset, cmp->pos, 0);
char quot = '\0'; // quotation character of a string value
while(cmp->pos < cmp->code.size){
while(cmp->pos < cmp->code.len){
c = cmp->code.data[cmp->pos];
// string argument reading
@ -143,7 +143,7 @@ static void readArguments(Compiler* cmp){
else if(c == '\r' || c == '\n' || c == ';'){
tok.length = cmp->pos - tok.begin;
if(tok.length > 0)
List_push(&cmp->tokens, Token, tok);
List_Token_push(&cmp->tokens, tok);
// cmp->line will be increased in lex()
return;
}
@ -152,7 +152,7 @@ static void readArguments(Compiler* cmp){
else if(c == ' ' || c == '\t'){
tok.length = cmp->pos - tok.begin;
if(tok.length > 0)
List_push(&cmp->tokens, Token, tok);
List_Token_push(&cmp->tokens, tok);
tok = Token_construct(TokenType_Unset, cmp->pos + 1, 0);
}
@ -169,7 +169,7 @@ static void readArguments(Compiler* cmp){
tok.type = TokenType_NamedDataPointer;
else if(c == '#')
tok.type = TokenType_NamedDataSize;
else if(isDigit(c))
else if(char_isDigit(c))
tok.type = TokenType_Number;
else tok.type = TokenType_Name;
}
@ -181,7 +181,7 @@ static void readArguments(Compiler* cmp){
// end of file
tok.length = cmp->pos - tok.begin;
if(tok.length > 0)
List_push(&cmp->tokens, Token, tok);
List_Token_push(&cmp->tokens, tok);
}
static void readInstruction(Compiler* cmp){
@ -189,14 +189,14 @@ static void readInstruction(Compiler* cmp){
cmp->pos++;
cmp->column++;
while(cmp->pos < cmp->code.size){
while(cmp->pos < cmp->code.len){
char c = cmp->code.data[cmp->pos];
// end of line
if(c == '\r' || c == '\n' || c == ';'){
tok.length = cmp->pos - tok.begin;
List_push(&cmp->tokens, Token, tok);
List_Token_push(&cmp->tokens, tok);
tok = Token_construct(TokenType_OperationEnd, cmp->pos, 1);
List_push(&cmp->tokens, Token, tok);
List_Token_push(&cmp->tokens, tok);
// cmp->line will be increased in lex()
return;
}
@ -204,14 +204,14 @@ static void readInstruction(Compiler* cmp){
// arguments begin
if(c == ' ' || c == '\t'){
tok.length = cmp->pos - tok.begin;
List_push(&cmp->tokens, Token, tok);
List_Token_push(&cmp->tokens, tok);
readArguments(cmp);
tok = Token_construct(TokenType_OperationEnd, cmp->pos, 1);
List_push(&cmp->tokens, Token, tok);
List_Token_push(&cmp->tokens, tok);
return;
}
if(!isAlphabeticalLower(c) && !isAlphabeticalUpper(c) && !isDigit(c)){
if(!char_isLatinLower(c) && !char_isLatinUpper(c) && !char_isDigit(c)){
setError(Error_unexpectedCharacter(c));
return;
}
@ -222,9 +222,9 @@ static void readInstruction(Compiler* cmp){
// end of file
tok.length = cmp->pos - tok.begin;
List_push(&cmp->tokens, Token, tok);
List_Token_push(&cmp->tokens, tok);
tok = Token_construct(TokenType_OperationEnd, cmp->pos, 1);
List_push(&cmp->tokens, Token, tok);
List_Token_push(&cmp->tokens, tok);
}
bool Compiler_lex(Compiler* cmp){
@ -232,7 +232,7 @@ bool Compiler_lex(Compiler* cmp){
cmp->state = CompilerState_Lexing;
cmp->column = 1;
while(cmp->pos < cmp->code.size){
while(cmp->pos < cmp->code.len){
char c = cmp->code.data[cmp->pos];
switch(c){
// skip blank characters
@ -248,7 +248,7 @@ bool Compiler_lex(Compiler* cmp){
break;
default:
// try read instruction
if(isAlphabeticalLower(c) || isAlphabeticalUpper(c))
if(char_isLatinLower(c) || char_isLatinUpper(c))
readInstruction(cmp);
else returnError(Error_unexpectedCharacter(c));
break;

View File

@ -1,42 +1,37 @@
#include "Compiler_internal.h"
#define setError(FORMAT, ...) {\
cmp->pos = ((Token*)cmp->tokens.data)[cmp->tok_i].begin;\
cmp->pos = cmp->tokens.data[cmp->tok_i].begin;\
Compiler_setError(cmp, FORMAT, ##__VA_ARGS__);\
}
#define setError_unexpectedToken(T) {\
str tok_str = str_copy(Compiler_constructTokenStr(cmp, T));\
str tok_str_tmp = Compiler_constructTokenStr(cmp, T);\
cmp->pos = T.begin;\
Compiler_setError(cmp, "unexpected token '%s'", tok_str.data);\
free(tok_str.data);\
Compiler_setError(cmp, "unexpected token '"FMT_str"'", tok_str_tmp.len, tok_str_tmp.data);\
}
#define setError_unexpectedTokenChar(T, I) {\
cmp->pos = T.begin + I;\
Compiler_setError(cmp, "unexpected token '%c'", cmp->code.data[cmp->pos]);\
Compiler_setError(cmp, "unexpected character '%c'", cmp->code.data[cmp->pos]);\
}
#define setError_unexpectedInstruction(T) {\
str tok_str = str_copy(Compiler_constructTokenStr(cmp, T));\
str tok_str_tmp = Compiler_constructTokenStr(cmp, T);\
cmp->pos = T.begin;\
Compiler_setError(cmp, "unexpected instruction '%s'", tok_str.data);\
free(tok_str.data);\
Compiler_setError(cmp, "unexpected instruction '"FMT_str"'", tok_str_tmp.len, tok_str_tmp.data);\
}
#define Error_TokenUnset "token of undefined type"
#define Error_BitSize "invalid size in bits"
#define List_pushAsBytes(L, VAL_PTR, START_INDEX, COUNT)\
List_push_size(L, (u8*)(VAL_PTR) + START_INDEX, COUNT)
static inline bool isVarSizeBits(u32 B) { return (B == 8 || B == 16 || B == 32 || B == 64); }
static NULLABLE(str) resolveEscapeSequences(Compiler* cmp, str src){
StringBuilder sb = StringBuilder_alloc(src.size);
StringBuilder sb = StringBuilder_alloc(src.len);
char c;
bool escaped = false;
for(u32 i = 0; i < src.size; i++){
for(u32 i = 0; i < src.len; i++){
c = src.data[i];
if(c == '\\'){
escaped = !escaped;
@ -71,7 +66,7 @@ static NULLABLE(str) resolveEscapeSequences(Compiler* cmp, str src){
StringBuilder_append_char(&sb, c);
break;
default:
setError_unexpectedTokenChar(((Token*)cmp->tokens.data)[cmp->tok_i], i);
setError_unexpectedTokenChar(cmp->tokens.data[cmp->tok_i], i);
StringBuilder_destroy(&sb);
return str_null;
}
@ -86,15 +81,15 @@ static void parseDataDefinition(Compiler* cmp, str instr_name, DataDefinition* d
i32 _element_size_bits;
str _instr_name_zero_terminated = str_copy(instr_name);
if(sscanf(_instr_name_zero_terminated.data, "const%i", &_element_size_bits) != 1 || !isVarSizeBits(_element_size_bits)){
free(_instr_name_zero_terminated.data);
str_destroy(_instr_name_zero_terminated);
setError(Error_BitSize);
return;
}
free(_instr_name_zero_terminated.data);
str_destroy(_instr_name_zero_terminated);
ddf->element_size = _element_size_bits / 8;
ddf->data_bytes = List_alloc(u8, 32);
ddf->data_bytes = List_u8_alloc(32);
Token tok = ((Token*)cmp->tokens.data)[++cmp->tok_i];
Token tok = cmp->tokens.data[++cmp->tok_i];
if(tok.type != TokenType_Name){
setError_unexpectedToken(tok);
return;
@ -104,8 +99,8 @@ static void parseDataDefinition(Compiler* cmp, str instr_name, DataDefinition* d
str processed_str = str_null;
ddf->name = tok_str;
while(++cmp->tok_i < List_len(&cmp->tokens, Token)){
tok = ((Token*)cmp->tokens.data)[cmp->tok_i];
while(++cmp->tok_i < cmp->tokens.len){
tok = cmp->tokens.data[cmp->tok_i];
switch(tok.type){
case TokenType_SingleLineComment:
case TokenType_MultiLineComment:
@ -126,13 +121,17 @@ static void parseDataDefinition(Compiler* cmp, str instr_name, DataDefinition* d
processed_str = str_copy(tok_str);
if(str_seekChar(tok_str, '.', 0) != -1){
f64 f = atof(processed_str.data);
List_pushAsBytes(&ddf->data_bytes, &f, 8 - ddf->element_size, ddf->element_size);
// for numbers smaller than 64 bits
u8* value_part = (u8*)&f + 8 - ddf->element_size;
List_u8_pushMany(&ddf->data_bytes, value_part, ddf->element_size);
}
else {
i64 i = atoll(processed_str.data);
List_pushAsBytes(&ddf->data_bytes, &i, 8 - ddf->element_size, ddf->element_size);
// for numbers smaller than 64 bits
u8* value_part = (u8*)&i + 8 - ddf->element_size;
List_u8_pushMany(&ddf->data_bytes, value_part, ddf->element_size);
}
free(processed_str.data);
str_destroy(processed_str);
break;
case TokenType_Char:
tok.begin += 1;
@ -140,20 +139,20 @@ static void parseDataDefinition(Compiler* cmp, str instr_name, DataDefinition* d
tok_str = Compiler_constructTokenStr(cmp, tok);
processed_str = resolveEscapeSequences(cmp, tok_str);
if(processed_str.size != ddf->element_size){
setError("can't fit char of size %i in %u bit variable", processed_str.size, _element_size_bits);
if(processed_str.len != ddf->element_size){
setError("can't fit char of size %i in %u bit variable", processed_str.len, _element_size_bits);
return;
}
List_pushAsBytes(&ddf->data_bytes, processed_str.data, 0, processed_str.size);
free(processed_str.data);
List_u8_pushMany(&ddf->data_bytes, (u8*)processed_str.data, processed_str.len);
str_destroy(processed_str);
break;
case TokenType_String:
tok.begin += 1;
tok.length -= 2;
tok_str = Compiler_constructTokenStr(cmp, tok);
processed_str = resolveEscapeSequences(cmp, tok_str);
List_pushAsBytes(&ddf->data_bytes, processed_str.data, 0, processed_str.size);
free(processed_str.data);
List_u8_pushMany(&ddf->data_bytes, (u8*)processed_str.data, processed_str.len);
str_destroy(processed_str);
break;
}
}
@ -161,7 +160,7 @@ static void parseDataDefinition(Compiler* cmp, str instr_name, DataDefinition* d
static void parseOperation(Compiler* cmp, str instr_name, Operation* operPtr){
Token tok = ((Token*)cmp->tokens.data)[cmp->tok_i];
Token tok = cmp->tokens.data[cmp->tok_i];
const Instruction* instr = Instruction_getByName(instr_name);
if(instr == NULL){
setError_unexpectedInstruction(tok);
@ -169,12 +168,12 @@ static void parseOperation(Compiler* cmp, str instr_name, Operation* operPtr){
}
operPtr->opcode = instr->opcode;
operPtr->args = List_alloc(Argument, 8);
operPtr->args = List_Argument_alloc(4);
Argument arg = (Argument){ .type = ArgumentType_Unset, .value.i = 0 };
str tok_str = str_null;
str processed_str = str_null;
while(++cmp->tok_i < List_len(&cmp->tokens, Token)){
tok = ((Token*)cmp->tokens.data)[cmp->tok_i];
while(++cmp->tok_i < cmp->tokens.len){
tok = cmp->tokens.data[cmp->tok_i];
switch(tok.type){
case TokenType_SingleLineComment:
case TokenType_MultiLineComment:
@ -200,8 +199,8 @@ static void parseOperation(Compiler* cmp, str instr_name, Operation* operPtr){
else {
arg.value.i = atoll(processed_str.data);
}
free(processed_str.data);
List_push(&operPtr->args, Argument, arg);
str_destroy(processed_str);
List_Argument_push(&operPtr->args, arg);
break;
case TokenType_Name:
tok_str = Compiler_constructTokenStr(cmp, tok);
@ -213,23 +212,23 @@ static void parseOperation(Compiler* cmp, str instr_name, Operation* operPtr){
arg.type = ArgumentType_VarDataName;
arg.value.data_name = tok_str;
}
List_push(&operPtr->args, Argument, arg);
List_Argument_push(&operPtr->args, arg);
break;
case TokenType_NamedDataPointer:
tok_str = Compiler_constructTokenStr(cmp, tok);
tok_str.data++;
tok_str.size--;
tok_str.len--;
arg.type = ArgumentType_ConstDataPointer;
arg.value.data_name = tok_str;
List_push(&operPtr->args, Argument, arg);
List_Argument_push(&operPtr->args, arg);
break;
case TokenType_NamedDataSize:
tok_str = Compiler_constructTokenStr(cmp, tok);
tok_str.data++;
tok_str.size--;
tok_str.len--;
arg.type = ArgumentType_ConstDataSize;
arg.value.data_name = tok_str;
List_push(&operPtr->args, Argument, arg);
List_Argument_push(&operPtr->args, arg);
break;
}
}
@ -241,8 +240,8 @@ bool Compiler_parse(Compiler* cmp){
Token tok;
Section* sec = NULL;
while(cmp->tok_i < List_len(&cmp->tokens, Token)){
tok = ((Token*)cmp->tokens.data)[cmp->tok_i];
while(cmp->tok_i < cmp->tokens.len){
tok = cmp->tokens.data[cmp->tok_i];
switch(tok.type){
case TokenType_Unset:
returnError(Error_TokenUnset);
@ -252,7 +251,7 @@ bool Compiler_parse(Compiler* cmp){
break;
case TokenType_Label:
// create new section
sec = List_expand_size(&cmp->ast.sections, sizeof(Section));
sec = List_Section_expand(&cmp->ast.sections, 1);
Section_construct(sec, Compiler_constructTokenStr(cmp, tok));
break;
case TokenType_Instruction:
@ -261,14 +260,12 @@ bool Compiler_parse(Compiler* cmp){
str instr_name = Compiler_constructTokenStr(cmp, tok);
// data definition starts with const
if(str_startsWith(instr_name, STR("const"))){
DataDefinition* dataDefPtr = List_expand_size(
&sec->data_definitions_list, sizeof(DataDefinition));
DataDefinition* dataDefPtr = List_DataDefinition_expand(&sec->data_definitions_list, 1);
memset(dataDefPtr, 0, sizeof(DataDefinition));
parseDataDefinition(cmp, instr_name, dataDefPtr);
}
else {
Operation* operPtr = List_expand_size(
&sec->operations_list, sizeof(Operation));
Operation* operPtr = List_Operation_expand(&sec->operations_list, 1);
memset(operPtr, 0, sizeof(Operation));
parseOperation(cmp, instr_name, operPtr);
}

View File

@ -1,5 +1,7 @@
#include "Token.h"
Array_declare(str);
static Array(str) _TokenType_str_array = ARRAY(str, {
STR("Unset"),
STR("SingleLineComment"),
@ -16,7 +18,7 @@ static Array(str) _TokenType_str_array = ARRAY(str, {
});
str TokenType_toString(TokenType t){
if(t >= Array_len(&_TokenType_str_array, str))
if(t >= _TokenType_str_array.len)
return STR("!!TokenType INDEX_ERROR!!");
return ((str*)_TokenType_str_array.data)[t];
return _TokenType_str_array.data[t];
}

View File

@ -26,4 +26,6 @@ typedef struct Token {
TokenType type : 8; // type of token (8 bits)
} Token;
List_declare(Token)
#define Token_construct(TYPE, BEGIN, LEN) ((Token){ .type = TYPE, .begin = BEGIN, .length = LEN })

View File

@ -2,5 +2,6 @@
/// NOP
i32 NOP_impl(VM* vm){
(void)vm;
return 0;
}

View File

@ -30,6 +30,7 @@ i32 JMP_impl(VM* vm);
i32 JNZ_impl(VM* vm);
i32 JZ_impl(VM* vm);
Array_declare(Instruction);
static const Array(Instruction) instructions_array = ARRAY(Instruction, {
Instruction_construct(NOP),
@ -63,7 +64,7 @@ static const Array(Instruction) instructions_array = ARRAY(Instruction, {
});
const Instruction* Instruction_getByOpcode(Opcode opcode){
if(opcode >= Array_len(&instructions_array, Instruction))
if((u32)opcode >= instructions_array.len)
return NULL;
return (Instruction*)instructions_array.data + opcode;
@ -75,7 +76,7 @@ static HashMap(Opcode)* opcode_map = NULL;
static void _opcode_map_construct(){
opcode_map = malloc(sizeof(*opcode_map));
HashMap_construct(opcode_map, Opcode, NULL);
for(u32 i = 0; i < Array_len(&instructions_array, Instruction); i++){
for(u32 i = 0; i < instructions_array.len; i++){
Instruction* instr_ptr = (Instruction*)instructions_array.data + i;
HashMap_tryPush(opcode_map, instr_ptr->name, &instr_ptr->opcode);
}
@ -87,7 +88,7 @@ const Instruction* Instruction_getByName(str name){
str name_upper = str_toUpper(name);
Opcode* op_ptr = HashMap_tryGetPtr(opcode_map, name_upper);
free(name_upper.data);
str_destroy(name_upper);
if(op_ptr == NULL)
return NULL;
return Instruction_getByOpcode(*op_ptr);

View File

@ -30,7 +30,7 @@ RegisterCode RegisterCode_parse(str r){
else check_code(dl)
else check_code(dh)
free(lower.data);
str_destroy(lower);
return code;
}
@ -60,15 +60,15 @@ str RegisterCode_toString(RegisterCode code){
break;
case 4:
buf_str.data += 1;
buf_str.size -= 1;
buf_str.len -= 1;
break;
case 7:
buf_str.data[0] = 'l';
buf_str.size -= 1;
buf_str.len -= 1;
break;
case 8:
buf_str.data[0] = 'h';
buf_str.size -= 1;
buf_str.len -= 1;
break;
}