updated tlibc
This commit is contained in:
parent
5397965319
commit
cf724a8d13
2
dependencies/tlibc
vendored
2
dependencies/tlibc
vendored
@ -1 +1 @@
|
||||
Subproject commit c415e2ca8ff51f41984ace8fe796187e6ad0fa27
|
||||
Subproject commit 6a7f0a8715c54029ef71ce8152cd690815f950aa
|
||||
14
dependencies/tlibc.config
vendored
14
dependencies/tlibc.config
vendored
@ -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"
|
||||
|
||||
@ -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)
|
||||
|
||||
11
project.config.user.default
Normal file
11
project.config.user.default
Normal 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"
|
||||
@ -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;
|
||||
|
||||
@ -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){
|
||||
|
||||
@ -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);
|
||||
}
|
||||
|
||||
@ -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);
|
||||
|
||||
|
||||
@ -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);
|
||||
|
||||
@ -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);
|
||||
|
||||
|
||||
@ -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);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@ -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"
|
||||
|
||||
@ -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;
|
||||
|
||||
@ -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);
|
||||
}
|
||||
|
||||
@ -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];
|
||||
}
|
||||
|
||||
@ -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 })
|
||||
|
||||
@ -2,5 +2,6 @@
|
||||
|
||||
/// NOP
|
||||
i32 NOP_impl(VM* vm){
|
||||
(void)vm;
|
||||
return 0;
|
||||
}
|
||||
|
||||
@ -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);
|
||||
|
||||
@ -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;
|
||||
}
|
||||
|
||||
|
||||
Loading…
Reference in New Issue
Block a user