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
|
#!/usr/bin/env bash
|
||||||
###########################################################
|
|
||||||
# Copy this file to your cbuild DEPENDENCY_CONFIGS_DIR #
|
# This is a dependency config.
|
||||||
# and enable it (ENABLED_DEPENDENCIES=tlibc). #
|
# You can copy it to another project to add tlibc dependency.
|
||||||
###########################################################
|
|
||||||
DEP_WORKING_DIR="dependencies/tlibc"
|
DEP_WORKING_DIR="$DEPENDENCIES_DIR/tlibc"
|
||||||
DEP_PRE_BUILD_COMMAND=""
|
|
||||||
DEP_POST_BUILD_COMMAND=""
|
|
||||||
if [[ "$TASK" = *_dbg ]]; then
|
if [[ "$TASK" = *_dbg ]]; then
|
||||||
dep_build_target="build_static_lib_dbg"
|
dep_build_target="build_static_lib_dbg"
|
||||||
else
|
else
|
||||||
dep_build_target="build_static_lib"
|
dep_build_target="build_static_lib"
|
||||||
fi
|
fi
|
||||||
|
DEP_PRE_BUILD_COMMAND=""
|
||||||
DEP_BUILD_COMMAND="cbuild $dep_build_target"
|
DEP_BUILD_COMMAND="cbuild $dep_build_target"
|
||||||
|
DEP_POST_BUILD_COMMAND=""
|
||||||
DEP_CLEAN_COMMAND="cbuild clean"
|
DEP_CLEAN_COMMAND="cbuild clean"
|
||||||
DEP_DYNAMIC_OUT_FILES=""
|
DEP_DYNAMIC_OUT_FILES=""
|
||||||
DEP_STATIC_OUT_FILES="bin/tlibc.a"
|
DEP_STATIC_OUT_FILES="bin/tlibc.a"
|
||||||
|
|||||||
@ -1,13 +1,22 @@
|
|||||||
#!/usr/bin/env bash
|
#!/usr/bin/env bash
|
||||||
CBUILD_VERSION=2.2.3
|
CBUILD_VERSION=2.3.2
|
||||||
|
|
||||||
PROJECT="tcpu"
|
PROJECT="tcpu"
|
||||||
CMP_C="gcc"
|
CMP_C="gcc"
|
||||||
CMP_CPP="g++"
|
CMP_CPP="g++"
|
||||||
STD_C="c11"
|
STD_C="c99"
|
||||||
STD_CPP="c++11"
|
STD_CPP="c++11"
|
||||||
WARN_C="-Wall -Wextra -Werror=return-type -Werror=pointer-arith -Wno-unused-parameter"
|
WARN_C="-Wall -Wextra
|
||||||
WARN_CPP="-Wall -Wextra -Werror=return-type -Werror=pointer-arith -Wno-unused-parameter"
|
-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_C="$(find src -name '*.c')"
|
||||||
SRC_CPP="$(find src -name '*.cpp')"
|
SRC_CPP="$(find src -name '*.cpp')"
|
||||||
|
|
||||||
@ -24,9 +33,9 @@ ENABLED_DEPENDENCIES='tlibc'
|
|||||||
# └── profile/ - gcc *.gcda profiling info files
|
# └── profile/ - gcc *.gcda profiling info files
|
||||||
OBJDIR="obj"
|
OBJDIR="obj"
|
||||||
OUTDIR="bin"
|
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
|
# OS-specific options
|
||||||
case "$OS" in
|
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"
|
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"
|
CPP_ARGS="$C_ARGS"
|
||||||
LINKER_ARGS="$CPP_ARGS $LINKER_LIBS"
|
LINKER_ARGS="$CPP_ARGS $LINKER_LIBS"
|
||||||
PRE_TASK_SCRIPT=
|
PRE_TASK_SCRIPT=""
|
||||||
TASK_SCRIPT=cbuild/default_tasks/build_exec.sh
|
TASK_SCRIPT="@cbuild/default_tasks/build_exec.sh"
|
||||||
POST_TASK_SCRIPT=
|
POST_TASK_SCRIPT="@cbuild/default_tasks/strip_exec.sh"
|
||||||
;;
|
;;
|
||||||
# creates executable with debug info and no optimizations
|
# creates executable with debug info and no optimizations
|
||||||
build_exec_dbg)
|
build_exec_dbg)
|
||||||
C_ARGS="-O0 -g3"
|
C_ARGS="-O0 -g3"
|
||||||
CPP_ARGS="$C_ARGS"
|
CPP_ARGS="$C_ARGS"
|
||||||
LINKER_ARGS="$CPP_ARGS $LINKER_LIBS"
|
LINKER_ARGS="$CPP_ARGS $LINKER_LIBS"
|
||||||
PRE_TASK_SCRIPT=
|
PRE_TASK_SCRIPT=""
|
||||||
TASK_SCRIPT=cbuild/default_tasks/build_exec.sh
|
TASK_SCRIPT="@cbuild/default_tasks/build_exec.sh"
|
||||||
POST_TASK_SCRIPT=
|
POST_TASK_SCRIPT=""
|
||||||
;;
|
;;
|
||||||
# creates shared library
|
# creates shared library
|
||||||
build_shared_lib)
|
build_shared_lib)
|
||||||
C_ARGS="-O2 -fpic -flto -shared"
|
C_ARGS="-O2 -fpic -flto -shared"
|
||||||
CPP_ARGS="$C_ARGS"
|
CPP_ARGS="$C_ARGS"
|
||||||
LINKER_ARGS="$CPP_ARGS $LINKER_LIBS -Wl,-soname,$SHARED_LIB_FILE"
|
LINKER_ARGS="$CPP_ARGS $LINKER_LIBS -Wl,-soname,$SHARED_LIB_FILE"
|
||||||
PRE_TASK_SCRIPT=
|
PRE_TASK_SCRIPT=""
|
||||||
TASK_SCRIPT=cbuild/default_tasks/build_shared_lib.sh
|
TASK_SCRIPT="@cbuild/default_tasks/build_shared_lib.sh"
|
||||||
POST_TASK_SCRIPT=
|
POST_TASK_SCRIPT=""
|
||||||
;;
|
;;
|
||||||
# creates shared library with debug symbols and no optimizations
|
# creates shared library with debug symbols and no optimizations
|
||||||
build_shared_lib_dbg)
|
build_shared_lib_dbg)
|
||||||
C_ARGS="-O0 -g3 -fpic -shared"
|
C_ARGS="-O0 -g3 -fpic -shared"
|
||||||
CPP_ARGS="$C_ARGS"
|
CPP_ARGS="$C_ARGS"
|
||||||
LINKER_ARGS="$CPP_ARGS $LINKER_LIBS -Wl,-soname,$SHARED_LIB_FILE"
|
LINKER_ARGS="$CPP_ARGS $LINKER_LIBS -Wl,-soname,$SHARED_LIB_FILE"
|
||||||
PRE_TASK_SCRIPT=
|
PRE_TASK_SCRIPT=""
|
||||||
TASK_SCRIPT=cbuild/default_tasks/build_shared_lib.sh
|
TASK_SCRIPT="@cbuild/default_tasks/build_shared_lib.sh"
|
||||||
POST_TASK_SCRIPT=
|
POST_TASK_SCRIPT=""
|
||||||
;;
|
;;
|
||||||
# creates static library
|
# creates static library
|
||||||
build_static_lib)
|
build_static_lib)
|
||||||
C_ARGS="-O2 -fpic -fdata-sections -ffunction-sections"
|
C_ARGS="-O2 -fpic -fdata-sections -ffunction-sections"
|
||||||
CPP_ARGS="$C_ARGS"
|
CPP_ARGS="$C_ARGS"
|
||||||
PRE_TASK_SCRIPT=
|
PRE_TASK_SCRIPT=""
|
||||||
TASK_SCRIPT=cbuild/default_tasks/build_static_lib.sh
|
TASK_SCRIPT="@cbuild/default_tasks/build_static_lib.sh"
|
||||||
POST_TASK_SCRIPT=
|
POST_TASK_SCRIPT=""
|
||||||
;;
|
;;
|
||||||
# creates static library with debug symbols and no optimizations
|
# creates static library with debug symbols and no optimizations
|
||||||
build_static_lib_dbg)
|
build_static_lib_dbg)
|
||||||
C_ARGS="-O0 -g3"
|
C_ARGS="-O0 -g3"
|
||||||
CPP_ARGS="$C_ARGS"
|
CPP_ARGS="$C_ARGS"
|
||||||
PRE_TASK_SCRIPT=
|
PRE_TASK_SCRIPT=""
|
||||||
TASK_SCRIPT=cbuild/default_tasks/build_static_lib.sh
|
TASK_SCRIPT="@cbuild/default_tasks/build_static_lib.sh"
|
||||||
POST_TASK_SCRIPT=
|
POST_TASK_SCRIPT=""
|
||||||
;;
|
;;
|
||||||
# executes $EXEC_FILE
|
# executes $EXEC_FILE
|
||||||
exec)
|
exec)
|
||||||
TASK_SCRIPT=cbuild/default_tasks/exec.sh
|
TASK_SCRIPT="@cbuild/default_tasks/exec.sh"
|
||||||
;;
|
;;
|
||||||
# executes $EXEC_FILE with valgrind memory checker
|
# executes $EXEC_FILE with valgrind memory checker
|
||||||
valgrind)
|
valgrind)
|
||||||
VALGRIND_ARGS="-s --read-var-info=yes --track-origins=yes --fullpath-after=$(pwd) --leak-check=full --show-leak-kinds=all"
|
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
|
TASK_SCRIPT="@cbuild/default_tasks/valgrind.sh"
|
||||||
;;
|
;;
|
||||||
# generates profiling info
|
# generates profiling info
|
||||||
profile)
|
profile)
|
||||||
@ -126,22 +135,25 @@ case "$TASK" in
|
|||||||
C_ARGS="-O2 -flto=auto -fuse-linker-plugin -fprofile-generate -fprofile-prefix-path=$(realpath $OBJDIR)/objects"
|
C_ARGS="-O2 -flto=auto -fuse-linker-plugin -fprofile-generate -fprofile-prefix-path=$(realpath $OBJDIR)/objects"
|
||||||
CPP_ARGS="$C_ARGS"
|
CPP_ARGS="$C_ARGS"
|
||||||
LINKER_ARGS="$CPP_ARGS $LINKER_LIBS"
|
LINKER_ARGS="$CPP_ARGS $LINKER_LIBS"
|
||||||
PRE_TASK_SCRIPT=cbuild/default_tasks/build_exec.sh
|
PRE_TASK_SCRIPT="@cbuild/default_tasks/build_exec.sh"
|
||||||
TASK_SCRIPT=cbuild/default_tasks/profile.sh
|
TASK_SCRIPT="@cbuild/default_tasks/profile.sh"
|
||||||
POST_TASK_SCRIPT=
|
POST_TASK_SCRIPT=""
|
||||||
;;
|
;;
|
||||||
# compiles program with -pg and runs it with gprof
|
# compiles program with -pg and runs it with gprof
|
||||||
# uses gprof2dot python script to generate function call tree (pip install gprof2dot)
|
# uses gprof2dot python script to generate function call tree (pip install gprof2dot)
|
||||||
# requires graphviz (https://www.graphviz.org/download/source/)
|
# requires graphviz (https://www.graphviz.org/download/source/)
|
||||||
gprof)
|
gprof)
|
||||||
OUTDIR="$OUTDIR/gprof"
|
OUTDIR="$OUTDIR/gprof"
|
||||||
# -pg adds code to executable, that generates file containing function call info (gmon.out)
|
# arguments that emit some call counter code and disable optimizations to see function names
|
||||||
C_ARGS="-O2 -flto=auto -fuse-linker-plugin -pg"
|
# 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"
|
CPP_ARGS="$C_ARGS"
|
||||||
LINKER_ARGS="$CPP_ARGS $LINKER_LIBS"
|
LINKER_ARGS="$CPP_ARGS $LINKER_LIBS"
|
||||||
PRE_TASK_SCRIPT=cbuild/default_tasks/build_exec.sh
|
PRE_TASK_SCRIPT="@cbuild/default_tasks/build_exec.sh"
|
||||||
TASK_SCRIPT=cbuild/default_tasks/gprof.sh
|
TASK_SCRIPT="@cbuild/default_tasks/gprof.sh"
|
||||||
POST_TASK_SCRIPT=
|
POST_TASK_SCRIPT=""
|
||||||
;;
|
;;
|
||||||
# compiles program and runs it with callgrind (part of valgrind)
|
# compiles program and runs it with callgrind (part of valgrind)
|
||||||
# uses gprof2dot python script to generate function call tree (pip install gprof2dot)
|
# 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"
|
C_ARGS="-O2 -flto=auto -fuse-linker-plugin"
|
||||||
CPP_ARGS="$C_ARGS"
|
CPP_ARGS="$C_ARGS"
|
||||||
LINKER_ARGS="$CPP_ARGS $LINKER_LIBS"
|
LINKER_ARGS="$CPP_ARGS $LINKER_LIBS"
|
||||||
PRE_TASK_SCRIPT=cbuild/default_tasks/build_exec.sh
|
PRE_TASK_SCRIPT="@cbuild/default_tasks/build_exec.sh"
|
||||||
TASK_SCRIPT=cbuild/default_tasks/callgrind.sh
|
TASK_SCRIPT="@cbuild/default_tasks/callgrind.sh"
|
||||||
POST_TASK_SCRIPT=
|
POST_TASK_SCRIPT=""
|
||||||
;;
|
;;
|
||||||
# compiles executable with sanitizers and executes it to find errors and warnings
|
# compiles executable with sanitizers and executes it to find errors and warnings
|
||||||
sanitize)
|
sanitize)
|
||||||
@ -163,19 +175,19 @@ case "$TASK" in
|
|||||||
C_ARGS="-O0 -g3 -fsanitize=undefined,address"
|
C_ARGS="-O0 -g3 -fsanitize=undefined,address"
|
||||||
CPP_ARGS="$C_ARGS"
|
CPP_ARGS="$C_ARGS"
|
||||||
LINKER_ARGS="$CPP_ARGS $LINKER_LIBS"
|
LINKER_ARGS="$CPP_ARGS $LINKER_LIBS"
|
||||||
PRE_TASK_SCRIPT=cbuild/default_tasks/build_exec.sh
|
PRE_TASK_SCRIPT="@cbuild/default_tasks/build_exec.sh"
|
||||||
TASK_SCRIPT=cbuild/default_tasks/exec.sh
|
TASK_SCRIPT="@cbuild/default_tasks/exec.sh"
|
||||||
POST_TASK_SCRIPT=
|
POST_TASK_SCRIPT=""
|
||||||
;;
|
;;
|
||||||
# rebuilds specified dependencies
|
# rebuilds specified dependencies
|
||||||
# EXAMPLE: `cbuild rebuild_dependencies=libexample1,fonts`
|
# EXAMPLE: `cbuild rebuild_dependencies=libexample1,fonts`
|
||||||
# 'all' can be specified to rebuild all dependencies
|
# 'all' can be specified to rebuild all dependencies
|
||||||
rebuild_dependencies)
|
rebuild_dependencies)
|
||||||
TASK_SCRIPT=cbuild/default_tasks/rebuild_dependencies.sh
|
TASK_SCRIPT="@cbuild/default_tasks/rebuild_dependencies.sh"
|
||||||
;;
|
;;
|
||||||
# deletes generated files
|
# deletes generated files
|
||||||
clean)
|
clean)
|
||||||
TASK_SCRIPT=cbuild/default_tasks/clean.sh
|
TASK_SCRIPT="@cbuild/default_tasks/clean.sh"
|
||||||
;;
|
;;
|
||||||
# nothing to do
|
# nothing to do
|
||||||
"" | no_task)
|
"" | 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;
|
static cstr _title = "TCPU v" TCPU_VERSION_CSTR;
|
||||||
|
|
||||||
bool Display_init(i32 w, i32 h, DisplayFlags flags){
|
bool Display_init(i32 w, i32 h, DisplayFlags flags){
|
||||||
|
(void)flags;
|
||||||
|
|
||||||
_d.width = w;
|
_d.width = w;
|
||||||
_d.height = h;
|
_d.height = h;
|
||||||
_d.window = NULL;
|
_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);
|
sprintf(position_str, "[at 0x%x][", (u32)vm->current_pos);
|
||||||
char* real_format = strcat_malloc(position_str, context, "] ", format);
|
char* real_format = strcat_malloc(position_str, context, "] ", format);
|
||||||
va_start(argv, 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);
|
va_end(argv);
|
||||||
free(real_format);
|
free(real_format);
|
||||||
if(buf == NULL){
|
if(buf == NULL){
|
||||||
|
|||||||
@ -1,5 +1,7 @@
|
|||||||
#include "AST.h"
|
#include "AST.h"
|
||||||
|
|
||||||
|
Array_declare(str);
|
||||||
|
|
||||||
static Array(str) _ArgumentType_str_array = ARRAY(str, {
|
static Array(str) _ArgumentType_str_array = ARRAY(str, {
|
||||||
STR("Unset"),
|
STR("Unset"),
|
||||||
STR("Register"),
|
STR("Register"),
|
||||||
@ -10,40 +12,40 @@ static Array(str) _ArgumentType_str_array = ARRAY(str, {
|
|||||||
});
|
});
|
||||||
|
|
||||||
str ArgumentType_toString(ArgumentType t){
|
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 INDEX_ERROR!!");
|
||||||
return ((str*)_ArgumentType_str_array.data)[t];
|
return _ArgumentType_str_array.data[t];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void Section_construct(Section* sec, str name){
|
void Section_construct(Section* sec, str name){
|
||||||
sec->name = name;
|
sec->name = name;
|
||||||
sec->data_definitions_list = List_alloc(DataDefinition, 256);
|
sec->data_definitions_list = List_DataDefinition_alloc(256);
|
||||||
sec->operations_list = List_alloc(Operation, 1024);
|
sec->operations_list = List_Operation_alloc(1024);
|
||||||
}
|
}
|
||||||
|
|
||||||
void Section_destroy(Section* sec){
|
void Section_destroy(Section* sec){
|
||||||
for(u32 i = 0; i < Array_len(&sec->data_definitions_list, DataDefinition); i++){
|
for(u32 i = 0; i < sec->data_definitions_list.len; i++){
|
||||||
DataDefinition* dd = (DataDefinition*)sec->data_definitions_list.data + i;
|
DataDefinition* dd = sec->data_definitions_list.data + i;
|
||||||
free(dd->data_bytes.data);
|
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++){
|
for(u32 i = 0; i < sec->operations_list.len; i++){
|
||||||
Operation* op = (Operation*)sec->operations_list.data + i;
|
Operation* op = sec->operations_list.data + i;
|
||||||
free(op->args.data);
|
List_Argument_destroy(&op->args);
|
||||||
}
|
}
|
||||||
free(sec->operations_list.data);
|
List_Operation_destroy(&sec->operations_list);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void AST_construct(AST* ast){
|
void AST_construct(AST* ast){
|
||||||
ast->sections = List_alloc(Section, 32);
|
ast->sections = List_Section_alloc(32);
|
||||||
}
|
}
|
||||||
|
|
||||||
void AST_destroy(AST* ast){
|
void AST_destroy(AST* ast){
|
||||||
for(u32 i = 0; i != Array_len(&ast->sections, Section); i++){
|
for(u32 i = 0; i != ast->sections.len; i++){
|
||||||
Section_destroy((Section*)ast->sections.data + 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/instructions.h"
|
||||||
#include "instructions/registers.h"
|
#include "instructions/registers.h"
|
||||||
#include "tlibc/collections/List.h"
|
#include "tlibc/collections/List.h"
|
||||||
|
#include "tlibc/collections/List_impl/List_u8.h"
|
||||||
|
|
||||||
typedef enum ArgumentType {
|
typedef enum ArgumentType {
|
||||||
ArgumentType_Unset,
|
ArgumentType_Unset,
|
||||||
@ -26,12 +27,16 @@ typedef struct Argument {
|
|||||||
} value;
|
} value;
|
||||||
} Argument;
|
} Argument;
|
||||||
|
|
||||||
|
List_declare(Argument);
|
||||||
|
|
||||||
|
|
||||||
typedef struct Operation {
|
typedef struct Operation {
|
||||||
List(Argument) args;
|
List(Argument) args;
|
||||||
Opcode opcode;
|
Opcode opcode;
|
||||||
} Operation;
|
} Operation;
|
||||||
|
|
||||||
|
List_declare(Operation);
|
||||||
|
|
||||||
|
|
||||||
typedef struct DataDefinition {
|
typedef struct DataDefinition {
|
||||||
str name;
|
str name;
|
||||||
@ -39,6 +44,8 @@ typedef struct DataDefinition {
|
|||||||
u32 element_size;
|
u32 element_size;
|
||||||
} DataDefinition;
|
} DataDefinition;
|
||||||
|
|
||||||
|
List_declare(DataDefinition);
|
||||||
|
|
||||||
|
|
||||||
typedef struct Section {
|
typedef struct Section {
|
||||||
str name;
|
str name;
|
||||||
@ -46,6 +53,8 @@ typedef struct Section {
|
|||||||
List(Operation) operations_list;
|
List(Operation) operations_list;
|
||||||
} Section;
|
} Section;
|
||||||
|
|
||||||
|
List_declare(Section);
|
||||||
|
|
||||||
void Section_construct(Section* Section, str name);
|
void Section_construct(Section* Section, str name);
|
||||||
void Section_destroy(Section* Section);
|
void Section_destroy(Section* Section);
|
||||||
|
|
||||||
|
|||||||
@ -4,20 +4,20 @@ void CompiledSection_construct(CompiledSection* ptr, str name){
|
|||||||
ptr->name = name;
|
ptr->name = name;
|
||||||
ptr->next = NULL;
|
ptr->next = NULL;
|
||||||
ptr->offset = 0;
|
ptr->offset = 0;
|
||||||
ptr->const_data_props_list = List_construct(ConstDataProps, NULL, 0, 0);
|
ptr->const_data_props_list = List_ConstDataProps_construct(NULL, 0, 0);
|
||||||
ptr->named_refs = List_construct(NamedRef, NULL, 0, 0);
|
ptr->named_refs = List_NamedRef_construct(NULL, 0, 0);
|
||||||
ptr->bytes = List_alloc(u8, 64);
|
ptr->bytes = List_u8_alloc(128);
|
||||||
}
|
}
|
||||||
|
|
||||||
void CompiledSection_destroy(CompiledSection* ptr){
|
void CompiledSection_destroy(CompiledSection* ptr){
|
||||||
free(ptr->const_data_props_list.data);
|
List_ConstDataProps_destroy(&ptr->const_data_props_list);
|
||||||
free(ptr->named_refs.data);
|
List_NamedRef_destroy(&ptr->named_refs);
|
||||||
free(ptr->bytes.data);
|
List_u8_destroy(&ptr->bytes);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void BinaryObject_construct(BinaryObject* ptr){
|
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->comp_sec_i_map, u32, NULL);
|
||||||
HashMap_construct(&ptr->const_data_props_map, ConstDataProps, NULL);
|
HashMap_construct(&ptr->const_data_props_map, ConstDataProps, NULL);
|
||||||
ptr->main_sec = NULL;
|
ptr->main_sec = NULL;
|
||||||
@ -25,11 +25,11 @@ void BinaryObject_construct(BinaryObject* ptr){
|
|||||||
}
|
}
|
||||||
|
|
||||||
void BinaryObject_destroy(BinaryObject* ptr){
|
void BinaryObject_destroy(BinaryObject* ptr){
|
||||||
for(u32 i = 0; i < List_len(&ptr->comp_sec_list, CompiledSection); i++){
|
for(u32 i = 0; i < ptr->comp_sec_list.len; i++){
|
||||||
CompiledSection* sec_ptr = (CompiledSection*)ptr->comp_sec_list.data + i;
|
CompiledSection* sec_ptr = ptr->comp_sec_list.data + i;
|
||||||
CompiledSection_destroy(sec_ptr);
|
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->comp_sec_i_map);
|
||||||
HashMap_destroy(&ptr->const_data_props_map);
|
HashMap_destroy(&ptr->const_data_props_map);
|
||||||
|
|||||||
@ -4,6 +4,7 @@
|
|||||||
#include "instructions/instructions.h"
|
#include "instructions/instructions.h"
|
||||||
#include "instructions/registers.h"
|
#include "instructions/registers.h"
|
||||||
#include "tlibc/collections/List.h"
|
#include "tlibc/collections/List.h"
|
||||||
|
#include "tlibc/collections/List_impl/List_u8.h"
|
||||||
#include "tlibc/collections/HashMap.h"
|
#include "tlibc/collections/HashMap.h"
|
||||||
#include "AST.h"
|
#include "AST.h"
|
||||||
|
|
||||||
@ -14,6 +15,8 @@ typedef struct ConstDataProps {
|
|||||||
u32 offset; // offset in bytes from section start
|
u32 offset; // offset in bytes from section start
|
||||||
} ConstDataProps;
|
} ConstDataProps;
|
||||||
|
|
||||||
|
List_declare(ConstDataProps)
|
||||||
|
|
||||||
#define ConstDataProps_construct(NAME, SIZE, OFFSET) ((ConstDataProps){ .name = NAME, .size = SIZE, .offset = OFFSET})
|
#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
|
u32 offset; // offset in bytes from section start
|
||||||
} NamedRef;
|
} NamedRef;
|
||||||
|
|
||||||
|
List_declare(NamedRef);
|
||||||
|
|
||||||
#define NamedRef_construct(NAME, TYPE, OFFSET) ((NamedRef){ .name = NAME, .type = TYPE, .offset = OFFSET})
|
#define NamedRef_construct(NAME, TYPE, OFFSET) ((NamedRef){ .name = NAME, .type = TYPE, .offset = OFFSET})
|
||||||
|
|
||||||
|
|
||||||
@ -41,6 +46,8 @@ typedef struct CompiledSection {
|
|||||||
List(u8) bytes;
|
List(u8) bytes;
|
||||||
} CompiledSection;
|
} CompiledSection;
|
||||||
|
|
||||||
|
List_declare(CompiledSection)
|
||||||
|
|
||||||
void CompiledSection_construct(CompiledSection* ptr, str name);
|
void CompiledSection_construct(CompiledSection* ptr, str name);
|
||||||
void CompiledSection_destroy(CompiledSection* ptr);
|
void CompiledSection_destroy(CompiledSection* ptr);
|
||||||
|
|
||||||
|
|||||||
@ -3,27 +3,27 @@
|
|||||||
void Compiler_construct(Compiler* cmp){
|
void Compiler_construct(Compiler* cmp){
|
||||||
memset(cmp, 0, sizeof(Compiler));
|
memset(cmp, 0, sizeof(Compiler));
|
||||||
cmp->state = CompilerState_Initial;
|
cmp->state = CompilerState_Initial;
|
||||||
cmp->tokens = List_alloc(Token, 4096);
|
cmp->tokens = List_Token_alloc(4096);
|
||||||
cmp->line_lengths = List_alloc(u32, 1024);
|
cmp->line_lengths = List_u32_alloc(1024);
|
||||||
AST_construct(&cmp->ast);
|
AST_construct(&cmp->ast);
|
||||||
BinaryObject_construct(&cmp->binary);
|
BinaryObject_construct(&cmp->binary);
|
||||||
}
|
}
|
||||||
|
|
||||||
void Compiler_destroy(Compiler* cmp){
|
void Compiler_destroy(Compiler* cmp){
|
||||||
free(cmp->code.data);
|
str_destroy(cmp->code);
|
||||||
free(cmp->tokens.data);
|
List_Token_destroy(&cmp->tokens);
|
||||||
free(cmp->line_lengths.data);
|
List_u32_destroy(&cmp->line_lengths);
|
||||||
AST_destroy(&cmp->ast);
|
AST_destroy(&cmp->ast);
|
||||||
BinaryObject_destroy(&cmp->binary);
|
BinaryObject_destroy(&cmp->binary);
|
||||||
}
|
}
|
||||||
|
|
||||||
CodePos Compiler_getLineAndColumn(Compiler* cmp, u32 pos){
|
CodePos Compiler_getLineAndColumn(Compiler* cmp, u32 pos){
|
||||||
u32 prev_lines_len = 0;
|
u32 prev_lines_len = 0;
|
||||||
if(pos >= cmp->code.size)
|
if(pos >= cmp->code.len)
|
||||||
return CodePos_create(0, 0);
|
return CodePos_create(0, 0);
|
||||||
|
|
||||||
for(u32 i = 0; i < List_len(&cmp->line_lengths, u32); i++){
|
for(u32 i = 0; i < cmp->line_lengths.len; i++){
|
||||||
u32 line_len = ((u32*)cmp->line_lengths.data)[i];
|
u32 line_len = cmp->line_lengths.data[i];
|
||||||
if(prev_lines_len + line_len > pos)
|
if(prev_lines_len + line_len > pos)
|
||||||
return CodePos_create(i + 1, pos + 1 - prev_lines_len);
|
return CodePos_create(i + 1, pos + 1 - prev_lines_len);
|
||||||
prev_lines_len += line_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, ...){
|
void _Compiler_setError(Compiler* cmp, cstr context, cstr format, ...){
|
||||||
// happens at the end of file
|
// happens at the end of file
|
||||||
if(cmp->pos >= cmp->code.size)
|
if(cmp->pos >= cmp->code.len)
|
||||||
cmp->pos = cmp->code.size - 1;
|
cmp->pos = cmp->code.len - 1;
|
||||||
char position_str[32];
|
char position_str[32];
|
||||||
CodePos code_pos = Compiler_getLineAndColumn(cmp, cmp->pos);
|
CodePos code_pos = Compiler_getLineAndColumn(cmp, cmp->pos);
|
||||||
sprintf(position_str, "[at %u:%u][", code_pos.line, code_pos.column);
|
sprintf(position_str, "[at %u:%u][", code_pos.line, code_pos.column);
|
||||||
char* real_format = strcat_malloc(position_str, context, "] ", format);
|
char* real_format = strcat_malloc(position_str, context, "] ", format);
|
||||||
va_list argv;
|
va_list argv;
|
||||||
va_start(argv, format);
|
va_start(argv, format);
|
||||||
char* NULLABLE(buf) = vsprintf_malloc(512, real_format, argv);
|
char* NULLABLE(buf) = vsprintf_malloc(real_format, argv);
|
||||||
va_end(argv);
|
va_end(argv);
|
||||||
free(real_format);
|
free(real_format);
|
||||||
if(buf == NULL){
|
if(buf == NULL){
|
||||||
@ -62,21 +62,24 @@ str Compiler_constructTokenStr(Compiler* cmp, Token t){
|
|||||||
return s;
|
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){
|
static bool compileSection(Compiler* cmp, Section* sec){
|
||||||
u32 cs_index = List_len(&cmp->binary.comp_sec_list, CompiledSection);
|
u32 cs_index = cmp->binary.comp_sec_list.len;
|
||||||
CompiledSection* cs = List_expand_size(&cmp->binary.comp_sec_list, sizeof(CompiledSection));
|
CompiledSection* cs = List_CompiledSection_expand(&cmp->binary.comp_sec_list, 1);
|
||||||
CompiledSection_construct(cs, sec->name);
|
CompiledSection_construct(cs, sec->name);
|
||||||
if(!HashMap_tryPush(&cmp->binary.comp_sec_i_map, cs->name, &cs_index)){
|
if(!HashMap_tryPush(&cmp->binary.comp_sec_i_map, cs->name, &cs_index)){
|
||||||
returnError("duplicate section '%s'", str_copy(sec->name).data);
|
returnError("duplicate section '%s'", str_copy(sec->name).data);
|
||||||
}
|
}
|
||||||
|
|
||||||
// compile code
|
// compile code
|
||||||
u8 zeroes[8] = {0, 0, 0, 0, 0, 0, 0, 0};
|
u8 zeroes_8[8];
|
||||||
for(u32 i = 0; i < List_len(&sec->operations_list, Operation); i++){
|
memset(zeroes_8, 0, sizeof(zeroes_8));
|
||||||
Operation* op = (Operation*)sec->operations_list.data + i;
|
for(u32 i = 0; i < sec->operations_list.len; i++){
|
||||||
List_pushMany(&cs->bytes, u8, &op->opcode, sizeof(op->opcode));
|
Operation* op = sec->operations_list.data + i;
|
||||||
for(u32 j = 0; j < List_len(&op->args, Argument); j++){
|
List_u8_pushStruct(&cs->bytes, &op->opcode);
|
||||||
Argument* arg = (Argument*)op->args.data + j;
|
for(u32 j = 0; j < op->args.len; j++){
|
||||||
|
Argument* arg = op->args.data + j;
|
||||||
switch(arg->type){
|
switch(arg->type){
|
||||||
case ArgumentType_VarDataName:
|
case ArgumentType_VarDataName:
|
||||||
returnError("argument type 'VarDataName' is not supported yet");
|
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);
|
returnError("invalid ArgumentType %i", arg->type);
|
||||||
|
|
||||||
case ArgumentType_Register:
|
case ArgumentType_Register:
|
||||||
List_push(&cs->bytes, u8, arg->value.register_code);
|
List_u8_push(&cs->bytes, arg->value.register_code);
|
||||||
break;
|
break;
|
||||||
case ArgumentType_ConstValue:
|
case ArgumentType_ConstValue:
|
||||||
List_pushMany(&cs->bytes, u8, &arg->value.i, 8);
|
List_u8_pushStruct(&cs->bytes, &arg->value.i);
|
||||||
break;
|
break;
|
||||||
case ArgumentType_ConstDataPointer:
|
case ArgumentType_ConstDataPointer:
|
||||||
List_push(&cs->named_refs, NamedRef, NamedRef_construct(
|
List_NamedRef_push(&cs->named_refs,
|
||||||
|
NamedRef_construct(
|
||||||
arg->value.data_name,
|
arg->value.data_name,
|
||||||
NamedRefType_Ptr,
|
NamedRefType_Ptr,
|
||||||
cs->bytes.size));
|
cs->bytes.len
|
||||||
List_pushMany(&cs->bytes, u8, zeroes, 8);
|
)
|
||||||
|
);
|
||||||
|
List_u8_pushStruct(&cs->bytes, zeroes_8);
|
||||||
break;
|
break;
|
||||||
case ArgumentType_ConstDataSize:
|
case ArgumentType_ConstDataSize:
|
||||||
List_push(&cs->named_refs, NamedRef, NamedRef_construct(
|
List_NamedRef_push(&cs->named_refs,
|
||||||
|
NamedRef_construct(
|
||||||
arg->value.data_name,
|
arg->value.data_name,
|
||||||
NamedRefType_Size,
|
NamedRefType_Size,
|
||||||
cs->bytes.size));
|
cs->bytes.len
|
||||||
List_pushMany(&cs->bytes, u8, zeroes, 8);
|
)
|
||||||
|
);
|
||||||
|
List_u8_pushStruct(&cs->bytes, zeroes_8);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// compile data
|
// compile data
|
||||||
for(u32 i = 0; i < List_len(&sec->data_definitions_list, DataDefinition); i++){
|
for(u32 i = 0; i < sec->data_definitions_list.len; i++){
|
||||||
DataDefinition* dd = (DataDefinition*)sec->data_definitions_list.data + i;
|
DataDefinition* dd = sec->data_definitions_list.data + i;
|
||||||
List_push(&cs->const_data_props_list, ConstDataProps,
|
ConstDataProps cd_props = ConstDataProps_construct(dd->name, dd->data_bytes.len, cs->bytes.len);
|
||||||
ConstDataProps_construct(dd->name, dd->data_bytes.size, cs->bytes.size));
|
List_ConstDataProps_push(&cs->const_data_props_list, cd_props);
|
||||||
List_pushMany(&cs->bytes, u8, dd->data_bytes.data, dd->data_bytes.size);
|
List_u8_pushMany(&cs->bytes, dd->data_bytes.data, dd->data_bytes.len);
|
||||||
}
|
}
|
||||||
|
|
||||||
// TODO: push padding
|
// TODO: push padding
|
||||||
@ -126,8 +135,8 @@ static bool compileBinary(Compiler* cmp){
|
|||||||
returnErrorIf_auto(cmp->state != CompilerState_Parsing);
|
returnErrorIf_auto(cmp->state != CompilerState_Parsing);
|
||||||
cmp->state = CompilerState_Compiling;
|
cmp->state = CompilerState_Compiling;
|
||||||
|
|
||||||
for(u32 i = 0; i < List_len(&cmp->ast.sections, Section); i++){
|
for(u32 i = 0; i < cmp->ast.sections.len; i++){
|
||||||
Section* sec = (Section*)cmp->ast.sections.data + i;
|
Section* sec = cmp->ast.sections.data + i;
|
||||||
if(!compileSection(cmp, sec)){
|
if(!compileSection(cmp, sec)){
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
@ -140,25 +149,25 @@ static bool compileBinary(Compiler* cmp){
|
|||||||
returnError("no 'main' section was defined");
|
returnError("no 'main' section was defined");
|
||||||
}
|
}
|
||||||
u32 main_sec_i = *main_sec_i_ptr;
|
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
|
// create linked list of CompiledSection where main is the first
|
||||||
CompiledSection* prev_sec = cmp->binary.main_sec;
|
CompiledSection* prev_sec = cmp->binary.main_sec;
|
||||||
u32 total_size = 0;
|
u32 total_size = 0;
|
||||||
for(u32 i = 0; i < List_len(&cmp->binary.comp_sec_list, CompiledSection); i++){
|
for(u32 i = 0; i < cmp->binary.comp_sec_list.len; i++){
|
||||||
CompiledSection* sec = (CompiledSection*)cmp->binary.comp_sec_list.data + i;
|
CompiledSection* sec = cmp->binary.comp_sec_list.data + i;
|
||||||
total_size += sec->bytes.size;
|
total_size += sec->bytes.len;
|
||||||
bool is_main_sec = str_equals(sec->name, main_sec_name);
|
bool is_main_sec = str_equals(sec->name, main_sec_name);
|
||||||
if(!is_main_sec){
|
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)){
|
if(!HashMap_tryPush(&cmp->binary.const_data_props_map, cd.name, &cd)){
|
||||||
returnError("duplicate named data '%s'", str_copy(cd.name).data);
|
returnError("duplicate named data '%s'", str_copy(cd.name).data);
|
||||||
}
|
}
|
||||||
for(u32 j = 0; j < List_len(&sec->const_data_props_list, ConstDataProps); j++){
|
for(u32 j = 0; j < sec->const_data_props_list.len; j++){
|
||||||
cd = ((ConstDataProps*)sec->const_data_props_list.data)[j];
|
cd = sec->const_data_props_list.data[j];
|
||||||
cd.offset += sec->offset;
|
cd.offset += sec->offset;
|
||||||
if(!HashMap_tryPush(&cmp->binary.const_data_props_map, cd.name, &cd)){
|
if(!HashMap_tryPush(&cmp->binary.const_data_props_map, cd.name, &cd)){
|
||||||
returnError("duplicate named data '%s'", str_copy(cd.name).data);
|
returnError("duplicate named data '%s'", str_copy(cd.name).data);
|
||||||
@ -172,10 +181,10 @@ static bool compileBinary(Compiler* cmp){
|
|||||||
}
|
}
|
||||||
|
|
||||||
// insert calculated offsets into sections
|
// insert calculated offsets into sections
|
||||||
for(u32 i = 0; i < List_len(&cmp->binary.comp_sec_list, CompiledSection); i++){
|
for(u32 i = 0; i < cmp->binary.comp_sec_list.len; i++){
|
||||||
CompiledSection* sec = (CompiledSection*)cmp->binary.comp_sec_list.data + i;
|
CompiledSection* sec = cmp->binary.comp_sec_list.data + i;
|
||||||
for(u32 j = 0; j < List_len(&sec->named_refs, NamedRef); j++){
|
for(u32 j = 0; j < sec->named_refs.len; j++){
|
||||||
NamedRef* ref = (NamedRef*)sec->named_refs.data +j;
|
NamedRef* ref = sec->named_refs.data + j;
|
||||||
|
|
||||||
ConstDataProps* target_data = HashMap_tryGetPtr(
|
ConstDataProps* target_data = HashMap_tryGetPtr(
|
||||||
&cmp->binary.const_data_props_map, ref->name);
|
&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;
|
CompiledSection* sec = cmp->binary.main_sec;
|
||||||
while(sec){
|
while(sec){
|
||||||
fwrite(sec->bytes.data, 1, sec->bytes.size, f);
|
fwrite(sec->bytes.data, 1, sec->bytes.len, f);
|
||||||
fflush(f);
|
fflush(f);
|
||||||
sec = sec->next;
|
sec = sec->next;
|
||||||
}
|
}
|
||||||
@ -232,7 +241,7 @@ bool Compiler_compile(Compiler* cmp, cstr source_file_name, cstr out_file_name,
|
|||||||
}
|
}
|
||||||
fclose(f);
|
fclose(f);
|
||||||
|
|
||||||
if(sb.buffer.size == 0){
|
if(sb.buffer.len == 0){
|
||||||
StringBuilder_destroy(&sb);
|
StringBuilder_destroy(&sb);
|
||||||
returnError("soucre file is empty");
|
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){
|
if(debug_log){
|
||||||
printf("------------------------------------[lines]------------------------------------\n");
|
printf("------------------------------------[lines]------------------------------------\n");
|
||||||
for(u32 i = 0; i < List_len(&cmp->line_lengths, u32); i++){
|
for(u32 i = 0; i < cmp->line_lengths.len; i++){
|
||||||
printf("[%u] length: %u\n", i+1, ((u32*)cmp->line_lengths.data)[i]);
|
printf("[%u] length: %u\n", i+1, cmp->line_lengths.data[i]);
|
||||||
}
|
}
|
||||||
|
|
||||||
printf("------------------------------------[tokens]-----------------------------------\n");
|
printf("------------------------------------[tokens]-----------------------------------\n");
|
||||||
for(u32 i = 0; i < List_len(&cmp->tokens, Token); i++){
|
for(u32 i = 0; i < cmp->tokens.len; i++){
|
||||||
Token t = ((Token*)cmp->tokens.data)[i];
|
Token t = cmp->tokens.data[i];
|
||||||
CodePos pos = Compiler_getLineAndColumn(cmp, t.begin);
|
CodePos pos = Compiler_getLineAndColumn(cmp, t.begin);
|
||||||
char* tokstr = malloc(4096);
|
char* tokstr = malloc(4096);
|
||||||
strncpy(tokstr, cmp->code.data + t.begin, t.length);
|
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){
|
if (debug_log){
|
||||||
printf("-------------------------------------[AST]-------------------------------------\n");
|
printf("-------------------------------------[AST]-------------------------------------\n");
|
||||||
for(u32 i = 0; i < List_len(&cmp->ast.sections, Section); i++){
|
for(u32 i = 0; i < cmp->ast.sections.len; i++){
|
||||||
Section* sec = (Section*)cmp->ast.sections.data + i;
|
Section* sec = cmp->ast.sections.data + i;
|
||||||
str tmpstr = str_copy(sec->name);
|
printf("section '"FMT_str"'\n", sec->name.len, sec->name.data);
|
||||||
printf("section '%s'\n", tmpstr.data);
|
|
||||||
free(tmpstr.data);
|
|
||||||
|
|
||||||
for(u32 j = 0; j < List_len(&sec->data_definitions_list, DataDefinition); j++){
|
for(u32 j = 0; j < sec->data_definitions_list.len; j++){
|
||||||
DataDefinition* dd = (DataDefinition*)sec->data_definitions_list.data + j;
|
DataDefinition* dd = sec->data_definitions_list.data + j;
|
||||||
tmpstr = str_copy(dd->name);
|
printf(" const%u "FMT_str" (len %u)\n",
|
||||||
printf(" const%u %s (len %u)\n", dd->element_size * 8, tmpstr.data,
|
dd->element_size * 8,
|
||||||
dd->data_bytes.size/dd->element_size);
|
dd->name.len, dd->name.data,
|
||||||
free(tmpstr.data);
|
dd->data_bytes.len/dd->element_size);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
for(u32 j = 0; j < List_len(&sec->operations_list, Operation); j++){
|
for(u32 j = 0; j < sec->operations_list.len; j++){
|
||||||
Operation* op = (Operation*)sec->operations_list.data + j;
|
Operation* op = sec->operations_list.data + j;
|
||||||
const Instruction* instr = Instruction_getByOpcode(op->opcode);
|
const Instruction* instr = Instruction_getByOpcode(op->opcode);
|
||||||
if(instr == NULL){
|
if(instr == NULL){
|
||||||
fclose(f);
|
fclose(f);
|
||||||
@ -314,8 +321,8 @@ bool Compiler_compile(Compiler* cmp, cstr source_file_name, cstr out_file_name,
|
|||||||
}
|
}
|
||||||
|
|
||||||
printf(" %s", instr->name.data);
|
printf(" %s", instr->name.data);
|
||||||
for(u32 k = 0; k < List_len(&op->args, Argument); k++){
|
for(u32 k = 0; k < op->args.len; k++){
|
||||||
Argument* arg = (Argument*)op->args.data + k;
|
Argument* arg = op->args.data + k;
|
||||||
printf(" %s(", ArgumentType_toString(arg->type).data);
|
printf(" %s(", ArgumentType_toString(arg->type).data);
|
||||||
|
|
||||||
switch(arg->type){
|
switch(arg->type){
|
||||||
@ -325,25 +332,19 @@ bool Compiler_compile(Compiler* cmp, cstr source_file_name, cstr out_file_name,
|
|||||||
case ArgumentType_Register:;
|
case ArgumentType_Register:;
|
||||||
str register_name = RegisterCode_toString(arg->value.register_code);
|
str register_name = RegisterCode_toString(arg->value.register_code);
|
||||||
printf("%s 0x%x", register_name.data, arg->value.register_code);
|
printf("%s 0x%x", register_name.data, arg->value.register_code);
|
||||||
free(register_name.data);
|
str_destroy(register_name);
|
||||||
break;
|
break;
|
||||||
case ArgumentType_ConstValue:
|
case ArgumentType_ConstValue:
|
||||||
printf(IFWIN("%lli", "%li"), arg->value.i);
|
printf(IFWIN("%lli", "%li"), arg->value.i);
|
||||||
break;
|
break;
|
||||||
case ArgumentType_ConstDataPointer:
|
case ArgumentType_ConstDataPointer:
|
||||||
tmpstr = str_copy(arg->value.data_name);
|
printf("@"FMT_str, arg->value.data_name.len, arg->value.data_name.data);
|
||||||
printf("@%s", tmpstr.data);
|
|
||||||
free(tmpstr.data);
|
|
||||||
break;
|
break;
|
||||||
case ArgumentType_ConstDataSize:
|
case ArgumentType_ConstDataSize:
|
||||||
tmpstr = str_copy(arg->value.data_name);
|
printf("#"FMT_str, arg->value.data_name.len, arg->value.data_name.data);
|
||||||
printf("#%s", tmpstr.data);
|
|
||||||
free(tmpstr.data);
|
|
||||||
break;
|
break;
|
||||||
case ArgumentType_VarDataName:
|
case ArgumentType_VarDataName:
|
||||||
tmpstr = str_copy(arg->value.data_name);
|
printf(FMT_str, arg->value.data_name.len, arg->value.data_name.data);
|
||||||
printf("%s", tmpstr.data);
|
|
||||||
free(tmpstr.data);
|
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -365,11 +366,10 @@ bool Compiler_compile(Compiler* cmp, cstr source_file_name, cstr out_file_name,
|
|||||||
success = compileBinary(cmp);
|
success = compileBinary(cmp);
|
||||||
|
|
||||||
if(debug_log){
|
if(debug_log){
|
||||||
for(u32 i = 0; i < List_len(&cmp->binary.comp_sec_list, CompiledSection); i++){
|
for(u32 i = 0; i < cmp->binary.comp_sec_list.len; i++){
|
||||||
CompiledSection* sec = (CompiledSection*)cmp->binary.comp_sec_list.data + i;
|
CompiledSection* sec = cmp->binary.comp_sec_list.data + i;
|
||||||
str tmpstr = str_copy(sec->name);
|
printf("compiled section '"FMT_str"' to %u bytes with offset 0x%x\n",
|
||||||
printf("compiled section '%s' to %u bytes with offset 0x%x\n", tmpstr.data, sec->bytes.size, sec->offset);
|
sec->name.len, sec->name.data, sec->bytes.len, sec->offset);
|
||||||
free(tmpstr.data);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -2,6 +2,7 @@
|
|||||||
#include "tlibc/std.h"
|
#include "tlibc/std.h"
|
||||||
#include "tlibc/string/str.h"
|
#include "tlibc/string/str.h"
|
||||||
#include "tlibc/collections/List.h"
|
#include "tlibc/collections/List.h"
|
||||||
|
#include "tlibc/collections/List_impl/List_u32.h"
|
||||||
#include "tlibc/collections/HashMap.h"
|
#include "tlibc/collections/HashMap.h"
|
||||||
#include "Token.h"
|
#include "Token.h"
|
||||||
#include "Binary.h"
|
#include "Binary.h"
|
||||||
|
|||||||
@ -9,7 +9,7 @@
|
|||||||
#define Error_endOfFile "unexpected end of file"
|
#define Error_endOfFile "unexpected end of file"
|
||||||
|
|
||||||
static void completeLine(Compiler* cmp){
|
static void completeLine(Compiler* cmp){
|
||||||
List_push(&cmp->line_lengths, u32, cmp->column);
|
List_u32_push(&cmp->line_lengths, cmp->column);
|
||||||
cmp->column = 0;
|
cmp->column = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -19,12 +19,12 @@ static void readCommentSingleLine(Compiler* cmp){
|
|||||||
cmp->column++;
|
cmp->column++;
|
||||||
cmp->pos++;
|
cmp->pos++;
|
||||||
|
|
||||||
while(cmp->pos < cmp->code.size){
|
while(cmp->pos < cmp->code.len){
|
||||||
c = cmp->code.data[cmp->pos];
|
c = cmp->code.data[cmp->pos];
|
||||||
// end of line
|
// end of line
|
||||||
if(c == '\r' || c == '\n'){
|
if(c == '\r' || c == '\n'){
|
||||||
tok.length = cmp->pos - tok.begin;
|
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()
|
// cmp->line will be increased in lex()
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@ -35,7 +35,7 @@ static void readCommentSingleLine(Compiler* cmp){
|
|||||||
|
|
||||||
// end of file
|
// end of file
|
||||||
tok.length = cmp->pos - tok.begin;
|
tok.length = cmp->pos - tok.begin;
|
||||||
List_push(&cmp->tokens, Token, tok);
|
List_Token_push(&cmp->tokens, tok);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void readCommentMultiLine(Compiler* cmp){
|
static void readCommentMultiLine(Compiler* cmp){
|
||||||
@ -44,12 +44,12 @@ static void readCommentMultiLine(Compiler* cmp){
|
|||||||
cmp->column++;
|
cmp->column++;
|
||||||
cmp->pos++;
|
cmp->pos++;
|
||||||
|
|
||||||
while(cmp->pos < cmp->code.size){
|
while(cmp->pos < cmp->code.len){
|
||||||
c = cmp->code.data[cmp->pos];
|
c = cmp->code.data[cmp->pos];
|
||||||
// closing comment
|
// closing comment
|
||||||
if(cmp->pos > tok.begin + 3 && c == '/' && cmp->code.data[cmp->pos - 1] == '*') {
|
if(cmp->pos > tok.begin + 3 && c == '/' && cmp->code.data[cmp->pos - 1] == '*') {
|
||||||
tok.length = cmp->pos - tok.begin + 1;
|
tok.length = cmp->pos - tok.begin + 1;
|
||||||
List_push(&cmp->tokens, Token, tok);
|
List_Token_push(&cmp->tokens, tok);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -65,7 +65,7 @@ static void readCommentMultiLine(Compiler* cmp){
|
|||||||
|
|
||||||
static void readComment(Compiler* cmp){
|
static void readComment(Compiler* cmp){
|
||||||
char c; // '/'
|
char c; // '/'
|
||||||
if(cmp->pos + 1 == cmp->code.size){
|
if(cmp->pos + 1 == cmp->code.len){
|
||||||
setError(Error_endOfFile);
|
setError(Error_endOfFile);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@ -91,19 +91,19 @@ static void readLabel(Compiler* cmp){
|
|||||||
cmp->column++;
|
cmp->column++;
|
||||||
Token tok = Token_construct(TokenType_Label, cmp->pos, 0);
|
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];
|
c = cmp->code.data[cmp->pos];
|
||||||
// end of line
|
// end of line
|
||||||
if(c == ':' || c == '\r' || c == '\n'){
|
if(c == ':' || c == '\r' || c == '\n'){
|
||||||
tok.length = cmp->pos - tok.begin;
|
tok.length = cmp->pos - tok.begin;
|
||||||
if(tok.length > 0)
|
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]));
|
else setError(Error_unexpectedCharacter(cmp->code.data[--cmp->pos]));
|
||||||
// cmp->line will be increased in lex()
|
// cmp->line will be increased in lex()
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if(!isAlphabeticalLower(c) && !isAlphabeticalUpper(c) && !isDigit(c) &&
|
if(!char_isLatinLower(c) && !char_isLatinUpper(c) && !char_isDigit(c) &&
|
||||||
c != '_' && c != '.'){
|
c != '_' && c != '.'){
|
||||||
setError(Error_unexpectedCharacter(c));
|
setError(Error_unexpectedCharacter(c));
|
||||||
return;
|
return;
|
||||||
@ -116,7 +116,7 @@ static void readLabel(Compiler* cmp){
|
|||||||
// end of file
|
// end of file
|
||||||
tok.length = cmp->pos - tok.begin;
|
tok.length = cmp->pos - tok.begin;
|
||||||
if(tok.length > 0)
|
if(tok.length > 0)
|
||||||
List_push(&cmp->tokens, Token, tok);
|
List_Token_push(&cmp->tokens, tok);
|
||||||
else setError(Error_endOfFile);
|
else setError(Error_endOfFile);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -125,7 +125,7 @@ static void readArguments(Compiler* cmp){
|
|||||||
Token tok = Token_construct(TokenType_Unset, cmp->pos, 0);
|
Token tok = Token_construct(TokenType_Unset, cmp->pos, 0);
|
||||||
char quot = '\0'; // quotation character of a string value
|
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];
|
c = cmp->code.data[cmp->pos];
|
||||||
|
|
||||||
// string argument reading
|
// string argument reading
|
||||||
@ -143,7 +143,7 @@ static void readArguments(Compiler* cmp){
|
|||||||
else if(c == '\r' || c == '\n' || c == ';'){
|
else if(c == '\r' || c == '\n' || c == ';'){
|
||||||
tok.length = cmp->pos - tok.begin;
|
tok.length = cmp->pos - tok.begin;
|
||||||
if(tok.length > 0)
|
if(tok.length > 0)
|
||||||
List_push(&cmp->tokens, Token, tok);
|
List_Token_push(&cmp->tokens, tok);
|
||||||
// cmp->line will be increased in lex()
|
// cmp->line will be increased in lex()
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@ -152,7 +152,7 @@ static void readArguments(Compiler* cmp){
|
|||||||
else if(c == ' ' || c == '\t'){
|
else if(c == ' ' || c == '\t'){
|
||||||
tok.length = cmp->pos - tok.begin;
|
tok.length = cmp->pos - tok.begin;
|
||||||
if(tok.length > 0)
|
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);
|
tok = Token_construct(TokenType_Unset, cmp->pos + 1, 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -169,7 +169,7 @@ static void readArguments(Compiler* cmp){
|
|||||||
tok.type = TokenType_NamedDataPointer;
|
tok.type = TokenType_NamedDataPointer;
|
||||||
else if(c == '#')
|
else if(c == '#')
|
||||||
tok.type = TokenType_NamedDataSize;
|
tok.type = TokenType_NamedDataSize;
|
||||||
else if(isDigit(c))
|
else if(char_isDigit(c))
|
||||||
tok.type = TokenType_Number;
|
tok.type = TokenType_Number;
|
||||||
else tok.type = TokenType_Name;
|
else tok.type = TokenType_Name;
|
||||||
}
|
}
|
||||||
@ -181,7 +181,7 @@ static void readArguments(Compiler* cmp){
|
|||||||
// end of file
|
// end of file
|
||||||
tok.length = cmp->pos - tok.begin;
|
tok.length = cmp->pos - tok.begin;
|
||||||
if(tok.length > 0)
|
if(tok.length > 0)
|
||||||
List_push(&cmp->tokens, Token, tok);
|
List_Token_push(&cmp->tokens, tok);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void readInstruction(Compiler* cmp){
|
static void readInstruction(Compiler* cmp){
|
||||||
@ -189,14 +189,14 @@ static void readInstruction(Compiler* cmp){
|
|||||||
cmp->pos++;
|
cmp->pos++;
|
||||||
cmp->column++;
|
cmp->column++;
|
||||||
|
|
||||||
while(cmp->pos < cmp->code.size){
|
while(cmp->pos < cmp->code.len){
|
||||||
char c = cmp->code.data[cmp->pos];
|
char c = cmp->code.data[cmp->pos];
|
||||||
// end of line
|
// end of line
|
||||||
if(c == '\r' || c == '\n' || c == ';'){
|
if(c == '\r' || c == '\n' || c == ';'){
|
||||||
tok.length = cmp->pos - tok.begin;
|
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);
|
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()
|
// cmp->line will be increased in lex()
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@ -204,14 +204,14 @@ static void readInstruction(Compiler* cmp){
|
|||||||
// arguments begin
|
// arguments begin
|
||||||
if(c == ' ' || c == '\t'){
|
if(c == ' ' || c == '\t'){
|
||||||
tok.length = cmp->pos - tok.begin;
|
tok.length = cmp->pos - tok.begin;
|
||||||
List_push(&cmp->tokens, Token, tok);
|
List_Token_push(&cmp->tokens, tok);
|
||||||
readArguments(cmp);
|
readArguments(cmp);
|
||||||
tok = Token_construct(TokenType_OperationEnd, cmp->pos, 1);
|
tok = Token_construct(TokenType_OperationEnd, cmp->pos, 1);
|
||||||
List_push(&cmp->tokens, Token, tok);
|
List_Token_push(&cmp->tokens, tok);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if(!isAlphabeticalLower(c) && !isAlphabeticalUpper(c) && !isDigit(c)){
|
if(!char_isLatinLower(c) && !char_isLatinUpper(c) && !char_isDigit(c)){
|
||||||
setError(Error_unexpectedCharacter(c));
|
setError(Error_unexpectedCharacter(c));
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@ -222,9 +222,9 @@ static void readInstruction(Compiler* cmp){
|
|||||||
|
|
||||||
// end of file
|
// end of file
|
||||||
tok.length = cmp->pos - tok.begin;
|
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);
|
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){
|
bool Compiler_lex(Compiler* cmp){
|
||||||
@ -232,7 +232,7 @@ bool Compiler_lex(Compiler* cmp){
|
|||||||
cmp->state = CompilerState_Lexing;
|
cmp->state = CompilerState_Lexing;
|
||||||
cmp->column = 1;
|
cmp->column = 1;
|
||||||
|
|
||||||
while(cmp->pos < cmp->code.size){
|
while(cmp->pos < cmp->code.len){
|
||||||
char c = cmp->code.data[cmp->pos];
|
char c = cmp->code.data[cmp->pos];
|
||||||
switch(c){
|
switch(c){
|
||||||
// skip blank characters
|
// skip blank characters
|
||||||
@ -248,7 +248,7 @@ bool Compiler_lex(Compiler* cmp){
|
|||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
// try read instruction
|
// try read instruction
|
||||||
if(isAlphabeticalLower(c) || isAlphabeticalUpper(c))
|
if(char_isLatinLower(c) || char_isLatinUpper(c))
|
||||||
readInstruction(cmp);
|
readInstruction(cmp);
|
||||||
else returnError(Error_unexpectedCharacter(c));
|
else returnError(Error_unexpectedCharacter(c));
|
||||||
break;
|
break;
|
||||||
|
|||||||
@ -1,42 +1,37 @@
|
|||||||
#include "Compiler_internal.h"
|
#include "Compiler_internal.h"
|
||||||
|
|
||||||
#define setError(FORMAT, ...) {\
|
#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__);\
|
Compiler_setError(cmp, FORMAT, ##__VA_ARGS__);\
|
||||||
}
|
}
|
||||||
|
|
||||||
#define setError_unexpectedToken(T) {\
|
#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;\
|
cmp->pos = T.begin;\
|
||||||
Compiler_setError(cmp, "unexpected token '%s'", tok_str.data);\
|
Compiler_setError(cmp, "unexpected token '"FMT_str"'", tok_str_tmp.len, tok_str_tmp.data);\
|
||||||
free(tok_str.data);\
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#define setError_unexpectedTokenChar(T, I) {\
|
#define setError_unexpectedTokenChar(T, I) {\
|
||||||
cmp->pos = T.begin + 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) {\
|
#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;\
|
cmp->pos = T.begin;\
|
||||||
Compiler_setError(cmp, "unexpected instruction '%s'", tok_str.data);\
|
Compiler_setError(cmp, "unexpected instruction '"FMT_str"'", tok_str_tmp.len, tok_str_tmp.data);\
|
||||||
free(tok_str.data);\
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#define Error_TokenUnset "token of undefined type"
|
#define Error_TokenUnset "token of undefined type"
|
||||||
#define Error_BitSize "invalid size in bits"
|
#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 inline bool isVarSizeBits(u32 B) { return (B == 8 || B == 16 || B == 32 || B == 64); }
|
||||||
|
|
||||||
static NULLABLE(str) resolveEscapeSequences(Compiler* cmp, str src){
|
static NULLABLE(str) resolveEscapeSequences(Compiler* cmp, str src){
|
||||||
StringBuilder sb = StringBuilder_alloc(src.size);
|
StringBuilder sb = StringBuilder_alloc(src.len);
|
||||||
char c;
|
char c;
|
||||||
bool escaped = false;
|
bool escaped = false;
|
||||||
for(u32 i = 0; i < src.size; i++){
|
for(u32 i = 0; i < src.len; i++){
|
||||||
c = src.data[i];
|
c = src.data[i];
|
||||||
if(c == '\\'){
|
if(c == '\\'){
|
||||||
escaped = !escaped;
|
escaped = !escaped;
|
||||||
@ -71,7 +66,7 @@ static NULLABLE(str) resolveEscapeSequences(Compiler* cmp, str src){
|
|||||||
StringBuilder_append_char(&sb, c);
|
StringBuilder_append_char(&sb, c);
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
setError_unexpectedTokenChar(((Token*)cmp->tokens.data)[cmp->tok_i], i);
|
setError_unexpectedTokenChar(cmp->tokens.data[cmp->tok_i], i);
|
||||||
StringBuilder_destroy(&sb);
|
StringBuilder_destroy(&sb);
|
||||||
return str_null;
|
return str_null;
|
||||||
}
|
}
|
||||||
@ -86,15 +81,15 @@ static void parseDataDefinition(Compiler* cmp, str instr_name, DataDefinition* d
|
|||||||
i32 _element_size_bits;
|
i32 _element_size_bits;
|
||||||
str _instr_name_zero_terminated = str_copy(instr_name);
|
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)){
|
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);
|
setError(Error_BitSize);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
free(_instr_name_zero_terminated.data);
|
str_destroy(_instr_name_zero_terminated);
|
||||||
ddf->element_size = _element_size_bits / 8;
|
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){
|
if(tok.type != TokenType_Name){
|
||||||
setError_unexpectedToken(tok);
|
setError_unexpectedToken(tok);
|
||||||
return;
|
return;
|
||||||
@ -104,8 +99,8 @@ static void parseDataDefinition(Compiler* cmp, str instr_name, DataDefinition* d
|
|||||||
str processed_str = str_null;
|
str processed_str = str_null;
|
||||||
ddf->name = tok_str;
|
ddf->name = tok_str;
|
||||||
|
|
||||||
while(++cmp->tok_i < List_len(&cmp->tokens, Token)){
|
while(++cmp->tok_i < cmp->tokens.len){
|
||||||
tok = ((Token*)cmp->tokens.data)[cmp->tok_i];
|
tok = cmp->tokens.data[cmp->tok_i];
|
||||||
switch(tok.type){
|
switch(tok.type){
|
||||||
case TokenType_SingleLineComment:
|
case TokenType_SingleLineComment:
|
||||||
case TokenType_MultiLineComment:
|
case TokenType_MultiLineComment:
|
||||||
@ -126,13 +121,17 @@ static void parseDataDefinition(Compiler* cmp, str instr_name, DataDefinition* d
|
|||||||
processed_str = str_copy(tok_str);
|
processed_str = str_copy(tok_str);
|
||||||
if(str_seekChar(tok_str, '.', 0) != -1){
|
if(str_seekChar(tok_str, '.', 0) != -1){
|
||||||
f64 f = atof(processed_str.data);
|
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 {
|
else {
|
||||||
i64 i = atoll(processed_str.data);
|
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;
|
break;
|
||||||
case TokenType_Char:
|
case TokenType_Char:
|
||||||
tok.begin += 1;
|
tok.begin += 1;
|
||||||
@ -140,20 +139,20 @@ static void parseDataDefinition(Compiler* cmp, str instr_name, DataDefinition* d
|
|||||||
tok_str = Compiler_constructTokenStr(cmp, tok);
|
tok_str = Compiler_constructTokenStr(cmp, tok);
|
||||||
processed_str = resolveEscapeSequences(cmp, tok_str);
|
processed_str = resolveEscapeSequences(cmp, tok_str);
|
||||||
|
|
||||||
if(processed_str.size != ddf->element_size){
|
if(processed_str.len != ddf->element_size){
|
||||||
setError("can't fit char of size %i in %u bit variable", processed_str.size, _element_size_bits);
|
setError("can't fit char of size %i in %u bit variable", processed_str.len, _element_size_bits);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
List_pushAsBytes(&ddf->data_bytes, processed_str.data, 0, processed_str.size);
|
List_u8_pushMany(&ddf->data_bytes, (u8*)processed_str.data, processed_str.len);
|
||||||
free(processed_str.data);
|
str_destroy(processed_str);
|
||||||
break;
|
break;
|
||||||
case TokenType_String:
|
case TokenType_String:
|
||||||
tok.begin += 1;
|
tok.begin += 1;
|
||||||
tok.length -= 2;
|
tok.length -= 2;
|
||||||
tok_str = Compiler_constructTokenStr(cmp, tok);
|
tok_str = Compiler_constructTokenStr(cmp, tok);
|
||||||
processed_str = resolveEscapeSequences(cmp, tok_str);
|
processed_str = resolveEscapeSequences(cmp, tok_str);
|
||||||
List_pushAsBytes(&ddf->data_bytes, processed_str.data, 0, processed_str.size);
|
List_u8_pushMany(&ddf->data_bytes, (u8*)processed_str.data, processed_str.len);
|
||||||
free(processed_str.data);
|
str_destroy(processed_str);
|
||||||
break;
|
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){
|
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);
|
const Instruction* instr = Instruction_getByName(instr_name);
|
||||||
if(instr == NULL){
|
if(instr == NULL){
|
||||||
setError_unexpectedInstruction(tok);
|
setError_unexpectedInstruction(tok);
|
||||||
@ -169,12 +168,12 @@ static void parseOperation(Compiler* cmp, str instr_name, Operation* operPtr){
|
|||||||
}
|
}
|
||||||
|
|
||||||
operPtr->opcode = instr->opcode;
|
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 };
|
Argument arg = (Argument){ .type = ArgumentType_Unset, .value.i = 0 };
|
||||||
str tok_str = str_null;
|
str tok_str = str_null;
|
||||||
str processed_str = str_null;
|
str processed_str = str_null;
|
||||||
while(++cmp->tok_i < List_len(&cmp->tokens, Token)){
|
while(++cmp->tok_i < cmp->tokens.len){
|
||||||
tok = ((Token*)cmp->tokens.data)[cmp->tok_i];
|
tok = cmp->tokens.data[cmp->tok_i];
|
||||||
switch(tok.type){
|
switch(tok.type){
|
||||||
case TokenType_SingleLineComment:
|
case TokenType_SingleLineComment:
|
||||||
case TokenType_MultiLineComment:
|
case TokenType_MultiLineComment:
|
||||||
@ -200,8 +199,8 @@ static void parseOperation(Compiler* cmp, str instr_name, Operation* operPtr){
|
|||||||
else {
|
else {
|
||||||
arg.value.i = atoll(processed_str.data);
|
arg.value.i = atoll(processed_str.data);
|
||||||
}
|
}
|
||||||
free(processed_str.data);
|
str_destroy(processed_str);
|
||||||
List_push(&operPtr->args, Argument, arg);
|
List_Argument_push(&operPtr->args, arg);
|
||||||
break;
|
break;
|
||||||
case TokenType_Name:
|
case TokenType_Name:
|
||||||
tok_str = Compiler_constructTokenStr(cmp, tok);
|
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.type = ArgumentType_VarDataName;
|
||||||
arg.value.data_name = tok_str;
|
arg.value.data_name = tok_str;
|
||||||
}
|
}
|
||||||
List_push(&operPtr->args, Argument, arg);
|
List_Argument_push(&operPtr->args, arg);
|
||||||
break;
|
break;
|
||||||
case TokenType_NamedDataPointer:
|
case TokenType_NamedDataPointer:
|
||||||
tok_str = Compiler_constructTokenStr(cmp, tok);
|
tok_str = Compiler_constructTokenStr(cmp, tok);
|
||||||
tok_str.data++;
|
tok_str.data++;
|
||||||
tok_str.size--;
|
tok_str.len--;
|
||||||
arg.type = ArgumentType_ConstDataPointer;
|
arg.type = ArgumentType_ConstDataPointer;
|
||||||
arg.value.data_name = tok_str;
|
arg.value.data_name = tok_str;
|
||||||
List_push(&operPtr->args, Argument, arg);
|
List_Argument_push(&operPtr->args, arg);
|
||||||
break;
|
break;
|
||||||
case TokenType_NamedDataSize:
|
case TokenType_NamedDataSize:
|
||||||
tok_str = Compiler_constructTokenStr(cmp, tok);
|
tok_str = Compiler_constructTokenStr(cmp, tok);
|
||||||
tok_str.data++;
|
tok_str.data++;
|
||||||
tok_str.size--;
|
tok_str.len--;
|
||||||
arg.type = ArgumentType_ConstDataSize;
|
arg.type = ArgumentType_ConstDataSize;
|
||||||
arg.value.data_name = tok_str;
|
arg.value.data_name = tok_str;
|
||||||
List_push(&operPtr->args, Argument, arg);
|
List_Argument_push(&operPtr->args, arg);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -241,8 +240,8 @@ bool Compiler_parse(Compiler* cmp){
|
|||||||
Token tok;
|
Token tok;
|
||||||
Section* sec = NULL;
|
Section* sec = NULL;
|
||||||
|
|
||||||
while(cmp->tok_i < List_len(&cmp->tokens, Token)){
|
while(cmp->tok_i < cmp->tokens.len){
|
||||||
tok = ((Token*)cmp->tokens.data)[cmp->tok_i];
|
tok = cmp->tokens.data[cmp->tok_i];
|
||||||
switch(tok.type){
|
switch(tok.type){
|
||||||
case TokenType_Unset:
|
case TokenType_Unset:
|
||||||
returnError(Error_TokenUnset);
|
returnError(Error_TokenUnset);
|
||||||
@ -252,7 +251,7 @@ bool Compiler_parse(Compiler* cmp){
|
|||||||
break;
|
break;
|
||||||
case TokenType_Label:
|
case TokenType_Label:
|
||||||
// create new section
|
// 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));
|
Section_construct(sec, Compiler_constructTokenStr(cmp, tok));
|
||||||
break;
|
break;
|
||||||
case TokenType_Instruction:
|
case TokenType_Instruction:
|
||||||
@ -261,14 +260,12 @@ bool Compiler_parse(Compiler* cmp){
|
|||||||
str instr_name = Compiler_constructTokenStr(cmp, tok);
|
str instr_name = Compiler_constructTokenStr(cmp, tok);
|
||||||
// data definition starts with const
|
// data definition starts with const
|
||||||
if(str_startsWith(instr_name, STR("const"))){
|
if(str_startsWith(instr_name, STR("const"))){
|
||||||
DataDefinition* dataDefPtr = List_expand_size(
|
DataDefinition* dataDefPtr = List_DataDefinition_expand(&sec->data_definitions_list, 1);
|
||||||
&sec->data_definitions_list, sizeof(DataDefinition));
|
|
||||||
memset(dataDefPtr, 0, sizeof(DataDefinition));
|
memset(dataDefPtr, 0, sizeof(DataDefinition));
|
||||||
parseDataDefinition(cmp, instr_name, dataDefPtr);
|
parseDataDefinition(cmp, instr_name, dataDefPtr);
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
Operation* operPtr = List_expand_size(
|
Operation* operPtr = List_Operation_expand(&sec->operations_list, 1);
|
||||||
&sec->operations_list, sizeof(Operation));
|
|
||||||
memset(operPtr, 0, sizeof(Operation));
|
memset(operPtr, 0, sizeof(Operation));
|
||||||
parseOperation(cmp, instr_name, operPtr);
|
parseOperation(cmp, instr_name, operPtr);
|
||||||
}
|
}
|
||||||
|
|||||||
@ -1,5 +1,7 @@
|
|||||||
#include "Token.h"
|
#include "Token.h"
|
||||||
|
|
||||||
|
Array_declare(str);
|
||||||
|
|
||||||
static Array(str) _TokenType_str_array = ARRAY(str, {
|
static Array(str) _TokenType_str_array = ARRAY(str, {
|
||||||
STR("Unset"),
|
STR("Unset"),
|
||||||
STR("SingleLineComment"),
|
STR("SingleLineComment"),
|
||||||
@ -16,7 +18,7 @@ static Array(str) _TokenType_str_array = ARRAY(str, {
|
|||||||
});
|
});
|
||||||
|
|
||||||
str TokenType_toString(TokenType t){
|
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 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)
|
TokenType type : 8; // type of token (8 bits)
|
||||||
} Token;
|
} Token;
|
||||||
|
|
||||||
|
List_declare(Token)
|
||||||
|
|
||||||
#define Token_construct(TYPE, BEGIN, LEN) ((Token){ .type = TYPE, .begin = BEGIN, .length = LEN })
|
#define Token_construct(TYPE, BEGIN, LEN) ((Token){ .type = TYPE, .begin = BEGIN, .length = LEN })
|
||||||
|
|||||||
@ -2,5 +2,6 @@
|
|||||||
|
|
||||||
/// NOP
|
/// NOP
|
||||||
i32 NOP_impl(VM* vm){
|
i32 NOP_impl(VM* vm){
|
||||||
|
(void)vm;
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|||||||
@ -30,6 +30,7 @@ i32 JMP_impl(VM* vm);
|
|||||||
i32 JNZ_impl(VM* vm);
|
i32 JNZ_impl(VM* vm);
|
||||||
i32 JZ_impl(VM* vm);
|
i32 JZ_impl(VM* vm);
|
||||||
|
|
||||||
|
Array_declare(Instruction);
|
||||||
|
|
||||||
static const Array(Instruction) instructions_array = ARRAY(Instruction, {
|
static const Array(Instruction) instructions_array = ARRAY(Instruction, {
|
||||||
Instruction_construct(NOP),
|
Instruction_construct(NOP),
|
||||||
@ -63,7 +64,7 @@ static const Array(Instruction) instructions_array = ARRAY(Instruction, {
|
|||||||
});
|
});
|
||||||
|
|
||||||
const Instruction* Instruction_getByOpcode(Opcode opcode){
|
const Instruction* Instruction_getByOpcode(Opcode opcode){
|
||||||
if(opcode >= Array_len(&instructions_array, Instruction))
|
if((u32)opcode >= instructions_array.len)
|
||||||
return NULL;
|
return NULL;
|
||||||
|
|
||||||
return (Instruction*)instructions_array.data + opcode;
|
return (Instruction*)instructions_array.data + opcode;
|
||||||
@ -75,7 +76,7 @@ static HashMap(Opcode)* opcode_map = NULL;
|
|||||||
static void _opcode_map_construct(){
|
static void _opcode_map_construct(){
|
||||||
opcode_map = malloc(sizeof(*opcode_map));
|
opcode_map = malloc(sizeof(*opcode_map));
|
||||||
HashMap_construct(opcode_map, Opcode, NULL);
|
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;
|
Instruction* instr_ptr = (Instruction*)instructions_array.data + i;
|
||||||
HashMap_tryPush(opcode_map, instr_ptr->name, &instr_ptr->opcode);
|
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);
|
str name_upper = str_toUpper(name);
|
||||||
Opcode* op_ptr = HashMap_tryGetPtr(opcode_map, name_upper);
|
Opcode* op_ptr = HashMap_tryGetPtr(opcode_map, name_upper);
|
||||||
free(name_upper.data);
|
str_destroy(name_upper);
|
||||||
if(op_ptr == NULL)
|
if(op_ptr == NULL)
|
||||||
return NULL;
|
return NULL;
|
||||||
return Instruction_getByOpcode(*op_ptr);
|
return Instruction_getByOpcode(*op_ptr);
|
||||||
|
|||||||
@ -30,7 +30,7 @@ RegisterCode RegisterCode_parse(str r){
|
|||||||
else check_code(dl)
|
else check_code(dl)
|
||||||
else check_code(dh)
|
else check_code(dh)
|
||||||
|
|
||||||
free(lower.data);
|
str_destroy(lower);
|
||||||
return code;
|
return code;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -60,15 +60,15 @@ str RegisterCode_toString(RegisterCode code){
|
|||||||
break;
|
break;
|
||||||
case 4:
|
case 4:
|
||||||
buf_str.data += 1;
|
buf_str.data += 1;
|
||||||
buf_str.size -= 1;
|
buf_str.len -= 1;
|
||||||
break;
|
break;
|
||||||
case 7:
|
case 7:
|
||||||
buf_str.data[0] = 'l';
|
buf_str.data[0] = 'l';
|
||||||
buf_str.size -= 1;
|
buf_str.len -= 1;
|
||||||
break;
|
break;
|
||||||
case 8:
|
case 8:
|
||||||
buf_str.data[0] = 'h';
|
buf_str.data[0] = 'h';
|
||||||
buf_str.size -= 1;
|
buf_str.len -= 1;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user