diff --git a/ccompiler/backend/riscv32/Makefile b/ccompiler/backend/riscv32/Makefile index abaf862..e3ee625 100644 --- a/ccompiler/backend/riscv32/Makefile +++ b/ccompiler/backend/riscv32/Makefile @@ -3,8 +3,11 @@ all: ccompiler run: ccompiler ./ccompiler test.c flat.bin +simple_test: + make -C tests/simple + ccompiler: frontend ir - gcc -g rv32ima_codegen.c -L../../frontend -lfrontend -L../../middleend -lir -o ccompiler + gcc -g rv32.c -I../../.. -L../../frontend -lfrontend -L../../middleend -lmiddleend -L../../../lib -lcore -o ccompiler frontend: make -C ../../frontend diff --git a/ccompiler/backend/riscv32/rv32ima_codegen.c b/ccompiler/backend/riscv32/rv32.c similarity index 93% rename from ccompiler/backend/riscv32/rv32ima_codegen.c rename to ccompiler/backend/riscv32/rv32.c index 40d3a24..94fb86a 100644 --- a/ccompiler/backend/riscv32/rv32ima_codegen.c +++ b/ccompiler/backend/riscv32/rv32.c @@ -1,16 +1,18 @@ #define RISCV_VM_BUILDIN_ECALL #include "rv32gen.h" #include +#include #include // 指令编码联合体(自动处理小端序) typedef union rv32code { uint32_t code; - uint8_t bytes[4]; + u8_t bytes[4]; } rv32code_t; #include "../../frontend/frontend.h" -#include "../../middleend/ir.h" +#include "../../middleend/middleend.h" + typedef struct { int code_pos; int to_idx; @@ -200,7 +202,7 @@ static int gen_instr(ir_bblock_t* block, ir_node_t* instr) { GENCODE(XOR(REG_T0, REG_T1, REG_T2)); break; default: - error("ERROR gen_instr op in riscv"); + LOG_ERROR("ERROR gen_instr op in riscv"); break; } offset = stack_offset(instr); @@ -213,7 +215,7 @@ static int gen_instr(ir_bblock_t* block, ir_node_t* instr) { int fidx = block_idx(instr->data.branch.false_bblock); int cidx = block_idx(ctx.cur_block); jmp_t* jmp; - jmp = xmalloc(sizeof(jmp_t)); + jmp = rt._malloc(sizeof(jmp_t)); *jmp = (jmp_t) { .base_offset = 8, .code_pos = ctx.codes.size, @@ -223,7 +225,7 @@ static int gen_instr(ir_bblock_t* block, ir_node_t* instr) { }; vector_push(ctx.jmp, jmp); GENCODE(BNEZ(REG_T0, 0)); - jmp = xmalloc(sizeof(jmp_t)); + jmp = rt._malloc(sizeof(jmp_t)); *jmp = (jmp_t) { .base_offset = 4, .code_pos = ctx.codes.size, @@ -237,7 +239,7 @@ static int gen_instr(ir_bblock_t* block, ir_node_t* instr) { } case IR_NODE_JUMP: { int idx = block_idx(instr->data.jump.target_bblock); - jmp_t* jmp = xmalloc(sizeof(jmp_t)); + jmp_t* jmp = rt._malloc(sizeof(jmp_t)); *jmp = (jmp_t) { .base_offset = 4, .code_pos = ctx.codes.size, @@ -251,7 +253,7 @@ static int gen_instr(ir_bblock_t* block, ir_node_t* instr) { } case IR_NODE_CALL: { if (instr->data.call.args.size > 8) { - error("can't add so much params"); + LOG_ERROR("can't add so much params"); } int param_regs[8] = { REG_A0, REG_A1, REG_A2, REG_A3, @@ -272,7 +274,7 @@ static int gen_instr(ir_bblock_t* block, ir_node_t* instr) { goto CALL_END; } - jmp_t* jmp = xmalloc(sizeof(jmp_t)); + jmp_t* jmp = rt._malloc(sizeof(jmp_t)); *jmp = (jmp_t) { .base_offset = ctx.cur_func_offset + ctx.cur_block_offset + len, .code_pos = ctx.codes.size, @@ -289,7 +291,7 @@ static int gen_instr(ir_bblock_t* block, ir_node_t* instr) { break; } default: - error("ERROR gen_instr in riscv"); + LOG_ERROR("ERROR gen_instr in riscv"); } return len; } @@ -320,7 +322,7 @@ static int gen_func(ir_func_t* func) { REG_A4, REG_A5, REG_A6, REG_A7 }; if (func->params.size > 8) { - error("can't add so much params"); + LOG_ERROR("can't add so much params"); } for (int i = 0; i < func->params.size; i++) { int offset = stack_offset(vector_at(func->params, i)); @@ -362,7 +364,7 @@ static int gen_code(ir_prog_t* prog) { for (int i = 0; i < prog->extern_funcs.size; i++) { if (system_func(prog->extern_funcs.data[i]->name) == -1) { - error("func %s not defined and not a system func", prog->extern_funcs.data[i]->name); + LOG_ERROR("func %s not defined and not a system func", prog->extern_funcs.data[i]->name); } } @@ -397,11 +399,15 @@ static int gen_code(ir_prog_t* prog) { return jmp_cache[i]; } } - error("main not found"); + LOG_ERROR("main not found"); } int main(int argc, char** argv) { // gcc rv32ima_codegen.c -o rv32gen.exe + + init_lib_core(); + log_set_level(NULL, LOG_LEVEL_NOTSET); + const char* infilename = "test.c"; const char* outfilename = "flat.bin"; if (argc >= 2) { @@ -417,9 +423,9 @@ int main(int argc, char** argv) { return 1; } - struct ASTNode* root = frontend(infilename, in, (sread_fn)fread_s); - gen_ir_from_ast(root); - int main_pos = gen_code(&prog); + ast_node_t* root = frontend(infilename, in, (sread_fn)fread_s); + ir_prog_t* prog = gen_ir_from_ast(root); + int main_pos = gen_code(prog); #define CRT_CODE_SIZE 16 rv32code_t gcodes[] = { diff --git a/ccompiler/backend/riscv32/rv_vm/Makefile b/ccompiler/backend/riscv32/rv_vm/Makefile new file mode 100644 index 0000000..53a488b --- /dev/null +++ b/ccompiler/backend/riscv32/rv_vm/Makefile @@ -0,0 +1,8 @@ +CC = gcc +CFLAGS = -g -Wall + +all = rv32-vm + +CFLAGS += -DDEFAULT_FILE='\"flat.bin\"' +rv32-vm: + $(CC) $(CFLAGS) -g -o rv32-vm .\ripes-vm.c diff --git a/test_rv_vm/mini-rv32ima.c b/ccompiler/backend/riscv32/rv_vm/mini-rv32ima.c similarity index 100% rename from test_rv_vm/mini-rv32ima.c rename to ccompiler/backend/riscv32/rv_vm/mini-rv32ima.c diff --git a/test_rv_vm/mini-rv32ima.h b/ccompiler/backend/riscv32/rv_vm/mini-rv32ima.h similarity index 100% rename from test_rv_vm/mini-rv32ima.h rename to ccompiler/backend/riscv32/rv_vm/mini-rv32ima.h diff --git a/test_rv_vm/README.md b/ccompiler/backend/riscv32/rv_vm/mini-rv32ima.md similarity index 100% rename from test_rv_vm/README.md rename to ccompiler/backend/riscv32/rv_vm/mini-rv32ima.md diff --git a/test_rv_vm/ripes-vm.c b/ccompiler/backend/riscv32/rv_vm/ripes-vm.c similarity index 97% rename from test_rv_vm/ripes-vm.c rename to ccompiler/backend/riscv32/rv_vm/ripes-vm.c index 3944090..94f0715 100644 --- a/test_rv_vm/ripes-vm.c +++ b/ccompiler/backend/riscv32/rv_vm/ripes-vm.c @@ -31,6 +31,10 @@ void ecall_handler(struct MiniRV32IMAState *state) { case 10: fprintf(stderr, "\nexit: %d\n", a0); exit(a0); + case 11: + // PrintChar + printf("%c", a0); + break; case 93: fprintf(stderr, "\nmain return code: %d\n", a0); exit(a0); @@ -40,7 +44,7 @@ void ecall_handler(struct MiniRV32IMAState *state) { case SYSCALL(1): // putchar putchar(a0); - + break; case SYSCALL(4): // input int scanf("%d", &a0); diff --git a/ccompiler/backend/riscv32/tests/simple/Makefile b/ccompiler/backend/riscv32/tests/simple/Makefile index 1e6afdb..3b05474 100644 --- a/ccompiler/backend/riscv32/tests/simple/Makefile +++ b/ccompiler/backend/riscv32/tests/simple/Makefile @@ -1,28 +1,30 @@ -VM := ../../rv32-vm -CC := ../../ccompiler -STD_CC := gcc +# VM := ../../rv32-vm +# CC := ../../ccompiler +# STD_CC := gcc -TESTS := $(wildcard *.c) +# TESTS := $(wildcard *.c) -# 定义所有测试目标 -TEST_TARGETS := $(patsubst %.c, %_test, $(TESTS)) +# # 定义所有测试目标 +# TEST_TARGETS := $(patsubst %.c, %_test, $(TESTS)) -all: $(TEST_TARGETS) +# all: $(TEST_TARGETS) -%_test: %.c - @$(STD_CC) -g -o $@ $< - @$(CC) $< flat.bin - @./$@ ; ret_gcc=$$? - @$(VM) flat.bin ; ret_vm=$$? - @echo "Testing $@" - @if [ $$ret_gcc -eq $$ret_vm ]; then \ - echo "$@ passed"; \ - else \ - echo "$@ failed: GCC returned $$ret_gcc, VM returned $$ret_vm"; \ - exit 1; \ - fi +# %_test: %.c +# @$(STD_CC) -g -o $@ $< +# @$(CC) $< flat.bin +# @./$@ ; ret_gcc=$$? +# @$(VM) flat.bin ; ret_vm=$$? +# @echo "Testing $@" +# @if [ $$ret_gcc -eq $$ret_vm ]; then \ +# echo "$@ passed"; \ +# else \ +# echo "$@ failed: GCC returned $$ret_gcc, VM returned $$ret_vm"; \ +# exit 1; \ +# fi -clean: - rm -f $(TEST_TARGETS) flat.bin +# clean: +# rm -f $(TEST_TARGETS) flat.bin -.PHONY: all clean +# .PHONY: all clean +all: + python test.py \ No newline at end of file diff --git a/ccompiler/frontend/Makefile b/ccompiler/frontend/Makefile index bfc4ace..e5194fe 100644 --- a/ccompiler/frontend/Makefile +++ b/ccompiler/frontend/Makefile @@ -1,7 +1,7 @@ # 编译器设置 CC = gcc AR = ar -CFLAGS = -g -Wall +CFLAGS = -g -Wall -I../.. # 源文件路径 LEXER_DIR = ./lexer @@ -15,7 +15,7 @@ SRCS = \ $(LEXER_DIR)/lexer.c \ $(LEXER_DIR)/token.c \ $(PARSER_DIR)/parser.c \ - $(AST_DIR)/ast.c \ + $(PARSER_DIR)/ast.c \ $(AST_DIR)/block.c \ $(AST_DIR)/decl.c \ $(AST_DIR)/expr.c \ diff --git a/ccompiler/frontend/frontend.c b/ccompiler/frontend/frontend.c index b23495f..ff7f59f 100644 --- a/ccompiler/frontend/frontend.c +++ b/ccompiler/frontend/frontend.c @@ -1,8 +1,10 @@ -#include "lexer/lexer.h" -#include "parser/symtab/symtab.h" +#include #include "frontend.h" +#include "parser/symtab/symtab.h" + +ast_node_t* frontend(const char* file, void* stream, sread_fn sread) { + init_lib_core(); -struct ASTNode* frontend(const char* file, void* stream, sread_fn sread) { lexer_t lexer; init_lexer(&lexer, file, stream, sread); diff --git a/ccompiler/frontend/frontend.h b/ccompiler/frontend/frontend.h index dd565ef..3acdfca 100644 --- a/ccompiler/frontend/frontend.h +++ b/ccompiler/frontend/frontend.h @@ -1,27 +1,9 @@ -#ifndef __FRONTEND_H__ -#define __FRONTEND_H__ +#ifndef __SMCC_FRONTEND_H__ +#define __SMCC_FRONTEND_H__ -#ifndef error -#include -#include -#include -#define STD_LIBRARY -#define error(...) do { fprintf(stderr, __VA_ARGS__); assert(0); } while (0) -#endif -#ifndef warn -#include -#define STD_LIBRARY -#define warn(...) do { fprintf(stdout, __VA_ARGS__); } while (0) -#endif - -#define xmalloc(size) malloc(size) - -#ifndef FRONTEND_IMPLEMENTATION +#include "lexer/lexer.h" #include "parser/parser.h" -#include "parser/ast/ast.h" - typedef int (*sread_fn)(void *dst_buf, int dst_size, int elem_size, int count, void *stream); -struct ASTNode* frontend(const char* file, void* stream, sread_fn sread); -#endif +ast_node_t* frontend(const char* file, void* stream, sread_fn sread); -#endif \ No newline at end of file +#endif diff --git a/ccompiler/frontend/lexer/lexer.c b/ccompiler/frontend/lexer/lexer.c index d6fe029..7cbf768 100644 --- a/ccompiler/frontend/lexer/lexer.c +++ b/ccompiler/frontend/lexer/lexer.c @@ -26,8 +26,8 @@ the distribution and installation instructions. Chris Fraser / cwf@aya.yale.edu David Hanson / drh@drhanson.net */ -#define FRONTEND_IMPLEMENTATION -#include "../frontend.h" +#include +#include "lexer_log.h" #include "token.h" #include "lexer.h" @@ -74,8 +74,9 @@ static inline int keyword_cmp(const char* name, int len) { return -1; // Not a keyword. } -void init_lexer(lexer_t* lexer, const char* file_name, void* stream, lexer_sread_fn sread) -{ +void init_lexer(lexer_t* lexer, const char* file_name, void* stream, lexer_sread_fn sread) { + init_lib_core(); + lexer->cur_ptr = lexer->end_ptr = (unsigned char*)&(lexer->buffer); lexer->index = 1; lexer->line = 1; @@ -96,10 +97,10 @@ static void flush_buffer(lexer_t* lexer) { lexer->cur_ptr = (unsigned char*)lexer->buffer; int read_size = LEXER_BUFFER_SIZE - num; - // TODO size_t to int maybe lose precision + // TODO rt_size_t to int maybe lose precision int got_size = lexer->sread(lexer->buffer + num, read_size, 1, read_size, lexer->stream); if (got_size < 0) { - error("lexer read error"); + LEX_ERROR("lexer read error"); } else if (got_size < read_size) { lexer->end_ptr += got_size; lexer->end_ptr[0] = '\0'; // EOF @@ -107,7 +108,7 @@ static void flush_buffer(lexer_t* lexer) { } else if (got_size == read_size) { lexer->end_ptr += got_size; } else { - error("lexer read error imposible got_size > read_size maybe overflow?"); + LEX_ERROR("lexer read error imposible got_size > read_size maybe overflow?"); } } @@ -153,8 +154,10 @@ static char got_slash(unsigned char* peek) { case 'r': return '\r'; case 't': return '\t'; case 'v': return '\v'; - default: error("Unknown escape character"); + default: break; } + LEX_ERROR("Unknown escape character"); + return -1; } static void parse_char_literal(lexer_t* lexer, tok_t* token) { @@ -168,7 +171,7 @@ static void parse_char_literal(lexer_t* lexer, tok_t* token) { val = *peek++; } - if (*peek++ != '\'') error("Unclosed character literal"); + if (*peek++ != '\'') LEX_ERROR("Unclosed character literal"); token->val.ch = val; lexer->cur_ptr = peek; token->val.have = 1; @@ -178,7 +181,7 @@ static void parse_char_literal(lexer_t* lexer, tok_t* token) { static void parse_string_literal(lexer_t* lexer, tok_t* token) { unsigned char* peek = lexer->cur_ptr + 1; // TODO string literal size check - char* dest = token->val.str = xmalloc(LEXER_MAX_TOKEN_SIZE + 1); + char* dest = token->val.str = rt._malloc(LEXER_MAX_TOKEN_SIZE + 1); int len = 0; while (*peek != '"') { @@ -189,7 +192,7 @@ static void parse_string_literal(lexer_t* lexer, tok_t* token) { *peek = got_slash(peek); } - if (len >= LEXER_MAX_TOKEN_SIZE) error("String too long"); + if (len >= LEXER_MAX_TOKEN_SIZE) LEX_ERROR("String too long"); dest[len++] = *peek++; } dest[len] = '\0'; @@ -431,7 +434,7 @@ void get_token(lexer_t* lexer, tok_t* token) { lexer->line++; tok = TOKEN_FLUSH; break; case '#': - warn("TODO: #define\n"); + LEX_WARN("Marroc does not support in lexer rather in preprocessor, it will be ignored"); goto_newline(lexer); tok = TOKEN_FLUSH; goto END; @@ -458,14 +461,14 @@ void get_token(lexer_t* lexer, tok_t* token) { case '_': // TOKEN_IDENT if ((*peek == 'L' && *peek == '\'') || (*peek == 'L' && *peek == '"')) { - error("unsupport wide-character char literal by `L` format"); + LEX_ERROR("unsupport wide-character char literal by `L` format"); } while (1) { if (peek == lexer->end_ptr) { - error("unsupport outof 64 length identifier"); + LEX_ERROR("unsupport outof 64 length identifier"); } if ((*peek >= 'a' && *peek <= 'z') || (*peek >= 'A' && *peek <= 'Z') || - (*peek == '_') || (*peek >= '0' && *peek <= '9')) { + (*peek == '_') || (*peek >= '0' && *peek <= '9')) { peek++; continue; } @@ -475,7 +478,7 @@ void get_token(lexer_t* lexer, tok_t* token) { int res = keyword_cmp((const char*)lexer->cur_ptr, peek - (lexer->cur_ptr)); if (res == -1) { int strlen = peek - lexer->cur_ptr; - unsigned char* str = xmalloc(strlen + 1); + unsigned char* str = rt._malloc(strlen + 1); constant.have = 1; constant.str = (char*)str; for (int i = 0; i < strlen; i++) { @@ -489,7 +492,7 @@ void get_token(lexer_t* lexer, tok_t* token) { tok = keywords[res].tok; break; } default: - error("unsupport char in sourse code `%c`", *(lexer->cur_ptr)); + LEX_ERROR("unsupport char in sourse code `%c`", *(lexer->cur_ptr)); break; } @@ -497,6 +500,7 @@ void get_token(lexer_t* lexer, tok_t* token) { END: token->val = constant; token->type = tok; + LEX_DEBUG("get token `%s` (ch: %c, int: %d)", get_tok_name(token->type), token->val.ch, token->val.i); } // get_token maybe got invalid (with parser) @@ -507,4 +511,3 @@ void get_valid_token(lexer_t* lexer, tok_t* token) { type = token->type; } while (type == TOKEN_FLUSH || type == TOKEN_LINE_COMMENT || type == TOKEN_BLOCK_COMMENT); } - diff --git a/ccompiler/frontend/lexer/lexer.h b/ccompiler/frontend/lexer/lexer.h index 726f4d0..3ae0b34 100644 --- a/ccompiler/frontend/lexer/lexer.h +++ b/ccompiler/frontend/lexer/lexer.h @@ -1,6 +1,7 @@ -#ifndef __LEXER_H__ -#define __LEXER_H__ +#ifndef __SMCC_LEXER_H__ +#define __SMCC_LEXER_H__ +#include #include "token.h" #ifndef LEXER_MAX_TOKEN_SIZE #define LEXER_MAX_TOKEN_SIZE 63 diff --git a/ccompiler/frontend/lexer/lexer_log.h b/ccompiler/frontend/lexer/lexer_log.h new file mode 100644 index 0000000..c7b9587 --- /dev/null +++ b/ccompiler/frontend/lexer/lexer_log.h @@ -0,0 +1,13 @@ +#ifndef __SMCC_LEXER_LOG_H__ +#define __SMCC_LEXER_LOG_H__ + +#include + +#define LEX_NOTSET( fmt, ...) LOG_NOTSET("LEXER: " fmt, ##__VA_ARGS__) +#define LEX_DEBUG( fmt, ...) LOG_DEBUG("LEXER: " fmt, ##__VA_ARGS__) +#define LEX_INFO( fmt, ...) LOG_INFO("LEXER: " fmt, ##__VA_ARGS__) +#define LEX_WARN( fmt, ...) LOG_WARN("LEXER: " fmt, ##__VA_ARGS__) +#define LEX_ERROR( fmt, ...) LOG_ERROR("LEXER: " fmt, ##__VA_ARGS__) +#define LEX_FATAL( fmt, ...) LOG_FATAL("LEXER: " fmt, ##__VA_ARGS__) + +#endif // __SMCC_LEXER_LOG_H__ diff --git a/ccompiler/frontend/lexer/tests/Makefile b/ccompiler/frontend/lexer/tests/Makefile index 91c4737..d6330b0 100644 --- a/ccompiler/frontend/lexer/tests/Makefile +++ b/ccompiler/frontend/lexer/tests/Makefile @@ -1,6 +1,7 @@ CC = gcc -CFLAGS = -g -Wall +CFLAGS = -g -Wall -I../../../.. SRC = ../lexer.c ../token.c +LIB = -L../../../../lib -lcore all = test_all @@ -8,10 +9,10 @@ test_all: test ./test run: - $(CC) $(CFLAGS) $(SRC) run.c -o run + $(CC) $(CFLAGS) $(SRC) run.c $(LIB) -o run test: - $(CC) $(CFLAGS) $(SRC) -o test test.c + $(CC) $(CFLAGS) $(SRC) $(LIB) -o test test.c clean: rm -f test run diff --git a/ccompiler/frontend/lexer/tests/run.c b/ccompiler/frontend/lexer/tests/run.c index 3e4cab9..fac6811 100644 --- a/ccompiler/frontend/lexer/tests/run.c +++ b/ccompiler/frontend/lexer/tests/run.c @@ -1,5 +1,6 @@ #include "../lexer.h" #include +#include // gcc -g ../lexer.c ../token.c test_lexer.c -o test_lexer /* tok_tConstant { @@ -18,9 +19,14 @@ tok_tConstant { int g_num; int g_num_arr[3]; int main(int argc, char* argv[]) { - int num = 0; + // int num = 0; + // You Must Be Call + init_lib_core(); + if (argc == 3 && strcmp(argv[2], "-nodebug") == 0) { + log_set_level(NULL, LOG_LEVEL_ALL & ~LOG_LEVEL_DEBUG); + } - const char* file_name = "test_lexer.c"; + const char* file_name = "run.c"; if (argc == 2) { file_name = argv[1]; } @@ -32,7 +38,7 @@ int main(int argc, char* argv[]) { printf("open file success\n"); lexer_t lexer; - init_lexer(&lexer, "test_lexter.c", fp, (lexer_sread_fn)fread_s); + init_lexer(&lexer, file_name, fp, (lexer_sread_fn)fread_s); tok_t tok; while (1) { @@ -40,7 +46,7 @@ int main(int argc, char* argv[]) { if (tok.type == TOKEN_EOF) { break; } - printf("line: %d, column: %d, type: %3d, typename: %s\n", - lexer.line, lexer.index, tok.type, get_tok_name(tok.type)); + // printf("line: %d, column: %d, type: %3d, typename: %s\n", + // lexer.line, lexer.index, tok.type, get_tok_name(tok.type)); } } diff --git a/ccompiler/frontend/lexer/token.c b/ccompiler/frontend/lexer/token.c index fc6c30d..e55fcb0 100644 --- a/ccompiler/frontend/lexer/token.c +++ b/ccompiler/frontend/lexer/token.c @@ -1,12 +1,12 @@ -#define FRONTEND_IMPLEMENTATION -#include "../frontend.h" +#include +#include "lexer_log.h" #include "token.h" #define ROUND_IDX(idx) ((idx) % tokbuf->cap) -tok_t* pop_tok(tok_buf_t* tokbuf) { +tok_t* pop_tok(tok_stream_t* tokbuf) { if (tokbuf->size == 0) { - error("no token to pop"); + LEX_ERROR("no token to pop"); return NULL; } int idx = tokbuf->cur; @@ -15,11 +15,11 @@ tok_t* pop_tok(tok_buf_t* tokbuf) { return tokbuf->buf + idx; } -void flush_peek_tok(tok_buf_t* tokbuf) { +void flush_peek_tok(tok_stream_t* tokbuf) { tokbuf->peek = tokbuf->cur; } -void init_tokbuf(tok_buf_t *tokbuf, void *stream, get_tokbuf_func gettok) { +void init_tokbuf(tok_stream_t *tokbuf, void *stream, tok_stream_get_func gettok) { tokbuf->cur = 0; tokbuf->end = 0; tokbuf->peek = 0; @@ -30,18 +30,19 @@ void init_tokbuf(tok_buf_t *tokbuf, void *stream, get_tokbuf_func gettok) { tokbuf->cap = 0; } -tok_t *peek_tok(tok_buf_t *tokbuf) { +tok_t *peek_tok(tok_stream_t *tokbuf) { + Assert(tokbuf->size <= tokbuf->cap); int idx = tokbuf->peek; tokbuf->peek = ROUND_IDX(idx + 1); - if (tokbuf->size >= tokbuf->cap) { - error("peek too deep, outof array size"); - } + if (idx == tokbuf->end) { if (tokbuf->size == tokbuf->cap) { - error("peek_tok buffer overflow"); + LEX_ERROR("peek_tok buffer overflow"); + return NULL; } if (tokbuf->gettok == NULL) { - error("peek_tok can not got tok"); + LEX_ERROR("peek_tok can not got tok"); + return NULL; } tokbuf->gettok(tokbuf->stream, &(tokbuf->buf[idx])); tokbuf->size++; @@ -51,15 +52,16 @@ tok_t *peek_tok(tok_buf_t *tokbuf) { return &(tokbuf->buf[idx]); } -tok_type_t peek_tok_type(tok_buf_t* tokbuf) { +tok_type_t peek_tok_type(tok_stream_t* tokbuf) { return peek_tok(tokbuf)->type; } -int expect_pop_tok(tok_buf_t* tokbuf, tok_type_t type) { +int expect_pop_tok(tok_stream_t* tokbuf, tok_type_t type) { flush_peek_tok(tokbuf); tok_t* tok = peek_tok(tokbuf); if (tok->type != type) { - error("expected tok: %s, got %s", get_tok_name(type), get_tok_name(tok->type)); + LEX_ERROR("expected tok `%s` but got `%s`", get_tok_name(type), get_tok_name(tok->type)); + return 0; } else { pop_tok(tokbuf); } diff --git a/ccompiler/frontend/lexer/token.h b/ccompiler/frontend/lexer/token.h index ae8bec9..b4cbe9a 100644 --- a/ccompiler/frontend/lexer/token.h +++ b/ccompiler/frontend/lexer/token.h @@ -51,10 +51,10 @@ enum CSTD_KEYWORD { X(flush , TOKEN_FLUSH) \ X("==" , TOKEN_EQ) \ X("=" , TOKEN_ASSIGN) \ - X("++" , TOKEN_ADD_ADD) \ + X("++" , TOKEN_ADD_ADD) \ X("+=" , TOKEN_ASSIGN_ADD) \ X("+" , TOKEN_ADD) \ - X("--" , TOKEN_SUB_SUB) \ + X("--" , TOKEN_SUB_SUB) \ X("-=" , TOKEN_ASSIGN_SUB) \ X("->" , TOKEN_DEREF) \ X("-" , TOKEN_SUB) \ @@ -134,7 +134,7 @@ typedef struct tok { tok_val_t val; } tok_t; -typedef struct tok_buf { +typedef struct tok_stream { int cur; int end; int peek; @@ -143,15 +143,15 @@ typedef struct tok_buf { tok_t* buf; void* stream; void (*gettok)(void* stream, tok_t* token); -} tok_buf_t; +} tok_stream_t; -typedef void(*get_tokbuf_func)(void* stream, tok_t* token); -void init_tokbuf(tok_buf_t* tokbuf, void* stream, get_tokbuf_func gettok); -tok_t* peek_tok(tok_buf_t* tokbuf); -tok_t* pop_tok(tok_buf_t* tokbuf); -void flush_peek_tok(tok_buf_t* tokbuf); -tok_type_t peek_tok_type(tok_buf_t* tokbuf); -int expect_pop_tok(tok_buf_t* tokbuf, tok_type_t type); +typedef void(*tok_stream_get_func)(void* stream, tok_t* token); +void init_tokbuf(tok_stream_t* tokbuf, void* stream, tok_stream_get_func gettok); +tok_t* peek_tok(tok_stream_t* tokbuf); +tok_t* pop_tok(tok_stream_t* tokbuf); +void flush_peek_tok(tok_stream_t* tokbuf); +tok_type_t peek_tok_type(tok_stream_t* tokbuf); +int expect_pop_tok(tok_stream_t* tokbuf, tok_type_t type); const char* get_tok_name(tok_type_t type); -#endif \ No newline at end of file +#endif diff --git a/ccompiler/middleend/ir.c b/ccompiler/frontend/parser/ast-gdb.py similarity index 100% rename from ccompiler/middleend/ir.c rename to ccompiler/frontend/parser/ast-gdb.py diff --git a/ccompiler/frontend/parser/ast/ast.c b/ccompiler/frontend/parser/ast.c similarity index 96% rename from ccompiler/frontend/parser/ast/ast.c rename to ccompiler/frontend/parser/ast.c index 2db771d..8f26038 100644 --- a/ccompiler/frontend/parser/ast/ast.c +++ b/ccompiler/frontend/parser/ast.c @@ -1,12 +1,11 @@ #include "ast.h" -#include "../parser.h" -struct ASTNode* new_ast_node(void) { - struct ASTNode* node = xmalloc(sizeof(struct ASTNode)); +ast_node_t* new_ast_node(void) { + ast_node_t* node = rt._malloc(sizeof(ast_node_t)); init_ast_node(node); return node; } -void init_ast_node(struct ASTNode* node) { +void init_ast_node(ast_node_t* node) { node->type = NT_INIT; for (int i = 0; i < sizeof(node->children) / sizeof(node->children[0]); i++) { @@ -14,7 +13,7 @@ void init_ast_node(struct ASTNode* node) { } } -// struct ASTNode* find_ast_node(struct ASTNode* node, ast_type_t type) { +// ast_node_t* find_ast_node(ast_node_t* node, ast_type_t type) { // } @@ -25,7 +24,7 @@ static void pnt_depth(int depth) { } } -// void pnt_ast(struct ASTNode* node, int depth) { +// void pnt_ast(ast_node_t* node, int depth) { // if (!node) return; // pnt_depth(depth); // switch (node->type) { diff --git a/ccompiler/frontend/parser/ast/ast.h b/ccompiler/frontend/parser/ast.h similarity index 66% rename from ccompiler/frontend/parser/ast/ast.h rename to ccompiler/frontend/parser/ast.h index 985f6f2..c6f19f6 100644 --- a/ccompiler/frontend/parser/ast/ast.h +++ b/ccompiler/frontend/parser/ast.h @@ -1,10 +1,9 @@ #ifndef __AST_H__ #define __AST_H__ -#include "../../frontend.h" -#include "../../lexer/lexer.h" -#include "../../../../libcore/vector.h" -#include "../type.h" +#include +#include "../lexer/lexer.h" +#include "type.h" typedef enum { NT_INIT, @@ -78,98 +77,98 @@ typedef enum { NT_TERM_TYPE, } ast_type_t; -typedef struct ASTNode { +typedef struct ast_node { ast_type_t type; union { void *children[6]; struct { - vector_header(children, struct ASTNode*); + vector_header(children, struct ast_node *); } root; struct { - vector_header(children, struct ASTNode*); + vector_header(children, struct ast_node *); } block; struct { - struct ASTNode* decl_node; + struct ast_node * decl_node; tok_t tok; } syms; struct { - vector_header(params, struct ASTNode*); + vector_header(params, struct ast_node *); } params; struct { - struct ASTNode* name; - struct ASTNode* params; - struct ASTNode* func_decl; + struct ast_node * name; + struct ast_node * params; + struct ast_node * func_decl; } call; struct { - struct ASTNode *type; - struct ASTNode *name; - struct ASTNode *expr_stmt; // optional + struct ast_node *type; + struct ast_node *name; + struct ast_node *expr_stmt; // optional void* data; } decl_val; struct { - struct ASTNode *ret; - struct ASTNode *name; - struct ASTNode *params; // array of params - struct ASTNode *def; + struct ast_node *ret; + struct ast_node *name; + struct ast_node *params; // array of params + struct ast_node *def; } decl_func; struct { - struct ASTNode *decl; - struct ASTNode *body; // optional + struct ast_node *decl; + struct ast_node *body; // optional void* data; } func; struct { - struct ASTNode *left; - struct ASTNode *right; - struct ASTNode *optional; // optional + struct ast_node *left; + struct ast_node *right; + struct ast_node *optional; // optional } expr; struct { - struct ASTNode *cond; - struct ASTNode *if_stmt; - struct ASTNode *else_stmt; // optional + struct ast_node *cond; + struct ast_node *if_stmt; + struct ast_node *else_stmt; // optional } if_stmt; struct { - struct ASTNode *cond; - struct ASTNode *body; + struct ast_node *cond; + struct ast_node *body; } switch_stmt; struct { - struct ASTNode *cond; - struct ASTNode *body; + struct ast_node *cond; + struct ast_node *body; } while_stmt; struct { - struct ASTNode *body; - struct ASTNode *cond; + struct ast_node *body; + struct ast_node *cond; } do_while_stmt; struct { - struct ASTNode *init; - struct ASTNode *cond; // optional - struct ASTNode *iter; // optional - struct ASTNode *body; + struct ast_node *init; + struct ast_node *cond; // optional + struct ast_node *iter; // optional + struct ast_node *body; } for_stmt; struct { - struct ASTNode *expr_stmt; // optional + struct ast_node *expr_stmt; // optional } return_stmt; struct { - struct ASTNode *label; + struct ast_node *label; } goto_stmt; struct { - struct ASTNode *label; + struct ast_node *label; } label_stmt; struct { - struct ASTNode *block; + struct ast_node *block; } block_stmt; struct { - struct ASTNode *expr_stmt; + struct ast_node *expr_stmt; } expr_stmt; }; } ast_node_t; -struct ASTNode* new_ast_node(void); -void init_ast_node(struct ASTNode* node); -void pnt_ast(struct ASTNode* node, int depth); +ast_node_t* new_ast_node(void); +void init_ast_node(ast_node_t* node); +void pnt_ast(ast_node_t* node, int depth); typedef struct parser parser_t; -typedef struct ASTNode* (*parse_func_t) (parser_t*); +typedef ast_node_t* (*parse_func_t) (parser_t*); void parse_prog(parser_t* parser); ast_node_t* parse_decl(parser_t* parser); @@ -182,8 +181,8 @@ ast_node_t* parse_expr(parser_t* parser); ast_node_t* parse_type(parser_t* parser); ast_node_t* new_ast_ident_node(tok_t* tok); -ast_node_t* expect_pop_ident(tok_buf_t* tokbuf); +ast_node_t* expect_pop_ident(tok_stream_t* tokbuf); -int peek_decl(tok_buf_t* tokbuf); +int peek_decl(tok_stream_t* tokbuf); #endif diff --git a/ccompiler/frontend/parser/ast/block.c b/ccompiler/frontend/parser/ast/block.c index 2e362c7..53ab003 100644 --- a/ccompiler/frontend/parser/ast/block.c +++ b/ccompiler/frontend/parser/ast/block.c @@ -1,5 +1,5 @@ -#include "ast.h" +#include "../ast.h" #include "../parser.h" #include "../symtab/symtab.h" @@ -17,7 +17,7 @@ ast_node_t* new_ast_node_block() { ast_node_t* parse_block(parser_t* parser) { symtab_enter_scope(parser->symtab); - tok_buf_t *tokbuf = &parser->tokbuf; + tok_stream_t *tokbuf = &parser->tokbuf; flush_peek_tok(tokbuf); tok_type_t ttype; ast_node_t* node = new_ast_node_block(); diff --git a/ccompiler/frontend/parser/ast/decl.c b/ccompiler/frontend/parser/ast/decl.c index 9a2580c..3962728 100644 --- a/ccompiler/frontend/parser/ast/decl.c +++ b/ccompiler/frontend/parser/ast/decl.c @@ -1,19 +1,19 @@ +#include "../ast.h" #include "../parser.h" -#include "ast.h" #include "../symtab/symtab.h" /** * 0 false * 1 true */ -int peek_decl(tok_buf_t* tokbuf) { +int peek_decl(tok_stream_t* tokbuf) { flush_peek_tok(tokbuf); switch (peek_tok_type(tokbuf)) { case TOKEN_STATIC: case TOKEN_EXTERN: case TOKEN_REGISTER: case TOKEN_TYPEDEF: - error("not impliment"); + LOG_ERROR("not impliment"); break; default: flush_peek_tok(tokbuf); @@ -36,7 +36,7 @@ int peek_decl(tok_buf_t* tokbuf) { } ast_node_t* parse_decl_val(parser_t* parser) { - tok_buf_t* tokbuf = &parser->tokbuf; + tok_stream_t* tokbuf = &parser->tokbuf; tok_type_t ttype; flush_peek_tok(tokbuf); @@ -55,28 +55,28 @@ ast_node_t* parse_decl_val(parser_t* parser) { if (ttype == TOKEN_ASSIGN) { node->decl_val.expr_stmt = parse_stmt(parser); if (node->decl_val.expr_stmt->type != NT_STMT_EXPR) { - error("parser_decl_val want stmt_expr"); + LOG_ERROR("parser_decl_val want stmt_expr"); } } else if (ttype == TOKEN_SEMICOLON) { pop_tok(tokbuf); expect_pop_tok(tokbuf, TOKEN_SEMICOLON); } else { - error("parser_decl_val syntax error"); + LOG_ERROR("parser_decl_val syntax error"); } return node; } ast_node_t* parse_decl(parser_t* parser) { - tok_buf_t* tokbuf = &parser->tokbuf; + tok_stream_t* tokbuf = &parser->tokbuf; flush_peek_tok(tokbuf); tok_type_t ttype; ast_node_t* node; if (peek_decl(tokbuf) == 0) { - error("syntax error expect decl_val TYPE"); + LOG_ERROR("syntax error expect decl_val TYPE"); } if (peek_tok_type(tokbuf) != TOKEN_IDENT) { - error("syntax error expect decl_val IDENT"); + LOG_ERROR("syntax error expect decl_val IDENT"); } ttype = peek_tok_type(tokbuf); @@ -89,7 +89,7 @@ ast_node_t* parse_decl(parser_t* parser) { node = parse_decl_val(parser); break; default: - error("syntax error expect decl_val ASSIGN or SEMICOLON"); + LOG_ERROR("syntax error expect decl_val ASSIGN or SEMICOLON"); return NULL; } return node; diff --git a/ccompiler/frontend/parser/ast/expr.c b/ccompiler/frontend/parser/ast/expr.c index e92d0b0..a5a7685 100644 --- a/ccompiler/frontend/parser/ast/expr.c +++ b/ccompiler/frontend/parser/ast/expr.c @@ -1,5 +1,5 @@ +#include "../ast.h" #include "../parser.h" -#include "ast.h" #include "../symtab/symtab.h" // Copy from `CParse` @@ -33,7 +33,7 @@ enum ParseType { PREFIX_PARSER, }; -static ast_node_t *parse_subexpression(tok_buf_t* tokbuf, symtab_t *symtab, enum Precedence prec); +static ast_node_t *parse_subexpression(tok_stream_t* tokbuf, symtab_t *symtab, enum Precedence prec); #define NEXT(prec) parse_subexpression(tokbuf, symtab, prec) static ast_node_t* gen_node2(ast_node_t* left, ast_node_t* right, @@ -72,7 +72,7 @@ static ast_node_t* gen_node2(ast_node_t* left, ast_node_t* right, // } } -static ast_node_t* parse_comma(tok_buf_t* tokbuf, symtab_t *symtab, ast_node_t* left) { +static ast_node_t* parse_comma(tok_stream_t* tokbuf, symtab_t *symtab, ast_node_t* left) { ast_node_t* node = new_ast_node(); node->type = NT_COMMA; node->expr.left = left; @@ -80,7 +80,7 @@ static ast_node_t* parse_comma(tok_buf_t* tokbuf, symtab_t *symtab, ast_node_t* return node; } -static ast_node_t* parse_assign(tok_buf_t* tokbuf, symtab_t *symtab, ast_node_t* left) { +static ast_node_t* parse_assign(tok_stream_t* tokbuf, symtab_t *symtab, ast_node_t* left) { flush_peek_tok(tokbuf); tok_type_t ttype = peek_tok_type(tokbuf); pop_tok(tokbuf); @@ -124,14 +124,14 @@ static ast_node_t* parse_assign(tok_buf_t* tokbuf, symtab_t *symtab, ast_node_t* left = gen_node2(left, NEXT(next), NT_XOR); break; default: - error("unsupported operator"); + LOG_ERROR("unsupported operator"); break; } node->expr.right = left; return node; } -static ast_node_t* parse_cmp(tok_buf_t* tokbuf, symtab_t *symtab, ast_node_t* left) { +static ast_node_t* parse_cmp(tok_stream_t* tokbuf, symtab_t *symtab, ast_node_t* left) { flush_peek_tok(tokbuf); tok_type_t ttype = peek_tok_type(tokbuf); pop_tok(tokbuf); @@ -164,12 +164,12 @@ static ast_node_t* parse_cmp(tok_buf_t* tokbuf, symtab_t *symtab, ast_node_t* le node->expr.right = NEXT(PREC_RELATIONAL); break; default: - error("invalid operator"); + LOG_ERROR("invalid operator"); } return node; } -static ast_node_t* parse_cal(tok_buf_t* tokbuf, symtab_t *symtab, ast_node_t* left) { +static ast_node_t* parse_cal(tok_stream_t* tokbuf, symtab_t *symtab, ast_node_t* left) { flush_peek_tok(tokbuf); tok_type_t ttype = peek_tok_type(tokbuf); pop_tok(tokbuf); @@ -230,7 +230,7 @@ static ast_node_t* parse_cal(tok_buf_t* tokbuf, symtab_t *symtab, ast_node_t* le return node; } -static ast_node_t* parse_call(tok_buf_t* tokbuf, symtab_t *symtab, ast_node_t* ident) { +static ast_node_t* parse_call(tok_stream_t* tokbuf, symtab_t *symtab, ast_node_t* ident) { ast_node_t* node = new_ast_node(); node->type = NT_TERM_CALL; node->call.name = ident; @@ -257,14 +257,14 @@ static ast_node_t* parse_call(tok_buf_t* tokbuf, symtab_t *symtab, ast_node_t* i ast_node_t* sym = symtab_lookup_symbol(symtab, name); // TODO check func is match if (sym == NULL || sym->type != NT_DECL_FUNC) { - error("function not decl %s", name); + LOG_ERROR("function not decl %s", name); } node->call.name = ident; node->call.func_decl = sym; return node; } -static ast_node_t* parse_paren(tok_buf_t* tokbuf, symtab_t *symtab, ast_node_t* left) { +static ast_node_t* parse_paren(tok_stream_t* tokbuf, symtab_t *symtab, ast_node_t* left) { flush_peek_tok(tokbuf); expect_pop_tok(tokbuf, TOKEN_L_PAREN); left = NEXT(PREC_EXPRESSION); @@ -273,7 +273,7 @@ static ast_node_t* parse_paren(tok_buf_t* tokbuf, symtab_t *symtab, ast_node_t* return left; } -typedef ast_node_t* (*parse_expr_fun_t)(tok_buf_t*, symtab_t* , ast_node_t*); +typedef ast_node_t* (*parse_expr_fun_t)(tok_stream_t*, symtab_t* , ast_node_t*); static struct expr_prec_table_t { parse_expr_fun_t parser; enum Precedence prec; @@ -322,7 +322,7 @@ static struct expr_prec_table_t { [TOKEN_L_PAREN] = {parse_paren, PREC_POSTFIX, INFIX_PARSER}, }; -static ast_node_t *parse_primary_expression(tok_buf_t* tokbuf, symtab_t *symtab) { +static ast_node_t *parse_primary_expression(tok_stream_t* tokbuf, symtab_t *symtab) { flush_peek_tok(tokbuf); tok_t* tok = peek_tok(tokbuf); @@ -335,7 +335,7 @@ static ast_node_t *parse_primary_expression(tok_buf_t* tokbuf, symtab_t *symtab) // node->data.data_type = TYPE_INT; break; case TOKEN_FLOAT_LITERAL: - warn("float not supported"); + LOG_WARN("float not supported"); break; case TOKEN_CHAR_LITERAL: // node->data.data_type = TYPE_CHAR; @@ -350,7 +350,7 @@ static ast_node_t *parse_primary_expression(tok_buf_t* tokbuf, symtab_t *symtab) } else { void *sym = symtab_lookup_symbol(symtab, tok->val.str); if (sym == NULL) { - error("undefined symbol but use %s", tok->val.str); + LOG_ERROR("undefined symbol but use %s", tok->val.str); } node->type = NT_TERM_IDENT; node->syms.decl_node = sym; @@ -364,7 +364,7 @@ END: return node; } -static ast_node_t *parse_subexpression(tok_buf_t* tokbuf, symtab_t *symtab, enum Precedence prec) { +static ast_node_t *parse_subexpression(tok_stream_t* tokbuf, symtab_t *symtab, enum Precedence prec) { tok_type_t ttype; struct expr_prec_table_t* work; ast_node_t* left; @@ -397,7 +397,7 @@ static ast_node_t *parse_subexpression(tok_buf_t* tokbuf, symtab_t *symtab, enum } ast_node_t* parse_expr(parser_t* parser) { - tok_buf_t* tokbuf = &(parser->tokbuf); + tok_stream_t* tokbuf = &(parser->tokbuf); symtab_t *symtab = parser->symtab; flush_peek_tok(tokbuf); tok_type_t ttype = peek_tok_type(tokbuf); @@ -419,7 +419,7 @@ ast_node_t* parse_expr(parser_t* parser) { case TOKEN_IDENT: return NEXT(PREC_EXPRESSION); default: - error("Want expr but not got %s", get_tok_name(ttype)); + LOG_ERROR("Want expr but not got %s", get_tok_name(ttype)); break; } } diff --git a/ccompiler/frontend/parser/ast/func.c b/ccompiler/frontend/parser/ast/func.c index aaba29d..afc0e09 100644 --- a/ccompiler/frontend/parser/ast/func.c +++ b/ccompiler/frontend/parser/ast/func.c @@ -1,13 +1,13 @@ +#include "../ast.h" #include "../parser.h" #include "../symtab/symtab.h" -#include "ast.h" #ifndef FUNC_PARAM_CACHE_SIZE #define FUNC_PARAM_CACHE_SIZE 32 // 合理初始值,可覆盖99%常见情况 #endif // TODO 语义分析压入符号表 -static void parse_params(parser_t* parser, tok_buf_t* cache, ast_node_t* node) { +static void parse_params(parser_t* parser, tok_stream_t* cache, ast_node_t* node) { flush_peek_tok(cache); tok_type_t ttype; ast_node_t *params = new_ast_node(); @@ -23,10 +23,10 @@ static void parse_params(parser_t* parser, tok_buf_t* cache, ast_node_t* node) { case TOKEN_ELLIPSIS: ttype = peek_tok_type(cache); if (ttype != TOKEN_R_PAREN) { - error("... must be a last parameter list (expect ')')"); + LOG_ERROR("... must be a last parameter list (expect ')')"); } // TODO - error("not implement"); + LOG_ERROR("not implement"); break; case TOKEN_IDENT: // TODO 静态数组 @@ -62,13 +62,13 @@ static void parse_params(parser_t* parser, tok_buf_t* cache, ast_node_t* node) { // flush_peek_tok(tokbuf); // continue; // } - // error("function expected ')' or ','\n"); + // LOG_ERROR("function expected ')' or ','\n"); } pop_tok(cache); } } -ast_type_t check_is_func_decl(tok_buf_t* tokbuf, tok_buf_t* cache) { +ast_type_t check_is_func_decl(tok_stream_t* tokbuf, tok_stream_t* cache) { expect_pop_tok(tokbuf, TOKEN_L_PAREN); int depth = 1; @@ -76,7 +76,7 @@ ast_type_t check_is_func_decl(tok_buf_t* tokbuf, tok_buf_t* cache) { tok_t* tok = peek_tok(tokbuf); pop_tok(tokbuf); if (cache->size >= cache->cap - 1) { - error("function parameter list too long"); + LOG_ERROR("function parameter list too long"); } cache->buf[cache->size++] = *tok; switch (tok->type) { @@ -100,7 +100,7 @@ ast_type_t check_is_func_decl(tok_buf_t* tokbuf, tok_buf_t* cache) { return NT_FUNC; break; default: - error("function define or decl need '{' or ';' but you don't got"); + LOG_ERROR("function define or decl need '{' or ';' but you don't got"); } } @@ -114,14 +114,14 @@ static ast_node_t* new_ast_node_funcdecl(ast_node_t* ret, ast_node_t* name) { } void parse_func(parser_t* parser) { - tok_buf_t* tokbuf = &(parser->tokbuf); + tok_stream_t* tokbuf = &(parser->tokbuf); flush_peek_tok(tokbuf); ast_node_t* ret_node = parse_type(parser); ast_node_t* name_node = expect_pop_ident(tokbuf); const char* func_name = name_node->syms.tok.val.str; ast_node_t* decl = new_ast_node_funcdecl(ret_node, name_node); - tok_buf_t cache; + tok_stream_t cache; init_tokbuf(&cache, NULL, NULL); cache.cap = FUNC_PARAM_CACHE_SIZE; tok_t buf[FUNC_PARAM_CACHE_SIZE]; @@ -132,12 +132,12 @@ void parse_func(parser_t* parser) { ast_node_t* prev = symtab_add_symbol(parser->symtab, func_name, decl, 1); if (prev != NULL) { if (prev->type != NT_DECL_FUNC) { - error("the symbol duplicate old is %d, new is func", prev->type); + LOG_ERROR("the symbol duplicate old is %d, new is func", prev->type); } // TODO check redeclare func is match if (type == NT_FUNC) { // TODO Free decl; - free(decl); + rt._free(decl); decl = prev; goto FUNC; } @@ -151,7 +151,7 @@ void parse_func(parser_t* parser) { FUNC: // 该data临时用于判断是否重复定义 if (decl->decl_func.def != NULL) { - error("redefinition of function %s", func_name); + LOG_ERROR("redefinition of function %s", func_name); } ast_node_t* node = new_ast_node(); diff --git a/ccompiler/frontend/parser/ast/program.c b/ccompiler/frontend/parser/ast/program.c index a6d3fc8..63478fa 100644 --- a/ccompiler/frontend/parser/ast/program.c +++ b/ccompiler/frontend/parser/ast/program.c @@ -1,5 +1,5 @@ +#include "../ast.h" #include "../parser.h" -#include "ast.h" #ifndef PROG_MAX_NODE_SIZE #define PROG_MAX_NODE_SIZE (1024 * 4) @@ -13,7 +13,7 @@ void parse_prog(parser_t* parser) { * same as * Program := Declaration* Definition* */ - tok_buf_t *tokbuf = &(parser->tokbuf); + tok_stream_t *tokbuf = &(parser->tokbuf); parser->root = new_ast_node(); ast_node_t* node; parser->root->type = NT_ROOT; diff --git a/ccompiler/frontend/parser/ast/stmt.c b/ccompiler/frontend/parser/ast/stmt.c index f5dc2a3..8106ce1 100644 --- a/ccompiler/frontend/parser/ast/stmt.c +++ b/ccompiler/frontend/parser/ast/stmt.c @@ -1,8 +1,8 @@ +#include "../ast.h" #include "../parser.h" -#include "ast.h" ast_node_t* parse_stmt(parser_t* parser) { - tok_buf_t* tokbuf = &parser->tokbuf; + tok_stream_t* tokbuf = &parser->tokbuf; flush_peek_tok(tokbuf); tok_type_t ttype = peek_tok_type(tokbuf); ast_node_t* node = new_ast_node(); @@ -66,7 +66,7 @@ ast_node_t* parse_stmt(parser_t* parser) { node->do_while_stmt.body = parse_stmt(parser); ttype = peek_tok_type(tokbuf); if (ttype != TOKEN_WHILE) { - error("expected while after do"); + LOG_ERROR("expected while after do"); } pop_tok(tokbuf); expect_pop_tok(tokbuf, TOKEN_L_PAREN); @@ -83,7 +83,7 @@ ast_node_t* parse_stmt(parser_t* parser) { pop_tok(tokbuf); ttype = peek_tok_type(tokbuf); if (ttype != TOKEN_L_PAREN) { - error("expected ( after for"); + LOG_ERROR("expected ( after for"); } pop_tok(tokbuf); @@ -170,7 +170,7 @@ ast_node_t* parse_stmt(parser_t* parser) { // find symbol table ttype = peek_tok_type(tokbuf); if (ttype != TOKEN_IDENT) { - error("expect identifier after goto"); + LOG_ERROR("expect identifier after goto"); } expect_pop_tok(tokbuf, TOKEN_SEMICOLON); // TODO filling label @@ -211,7 +211,7 @@ ast_node_t* parse_stmt(parser_t* parser) { case TOKEN_CASE: { // TODO label switch pop_tok(tokbuf); - error("unimplemented switch label"); + LOG_ERROR("unimplemented switch label"); node->label_stmt.label = parse_expr(parser); // TODO 该表达式为const int expect_pop_tok(tokbuf, TOKEN_COLON); @@ -234,7 +234,7 @@ ast_node_t* parse_stmt(parser_t* parser) { flush_peek_tok(tokbuf); ttype = peek_tok_type(tokbuf); if (ttype != TOKEN_SEMICOLON) { - error("exp must end with \";\""); + LOG_ERROR("exp must end with \";\""); } pop_tok(tokbuf); node->type = NT_STMT_EXPR; diff --git a/ccompiler/frontend/parser/ast/term.c b/ccompiler/frontend/parser/ast/term.c index 797c45c..fccb248 100644 --- a/ccompiler/frontend/parser/ast/term.c +++ b/ccompiler/frontend/parser/ast/term.c @@ -1,10 +1,10 @@ +#include "../ast.h" #include "../parser.h" #include "../type.h" -#include "ast.h" ast_node_t* new_ast_ident_node(tok_t* tok) { if (tok->type != TOKEN_IDENT) { - error("syntax error: want identifier but got %d", tok->type); + LOG_ERROR("syntax error: want identifier but got %d", tok->type); } ast_node_t* node = new_ast_node(); node->type = NT_TERM_IDENT; @@ -13,7 +13,7 @@ ast_node_t* new_ast_ident_node(tok_t* tok) { return node; } -ast_node_t* expect_pop_ident(tok_buf_t* tokbuf) { +ast_node_t* expect_pop_ident(tok_stream_t* tokbuf) { flush_peek_tok(tokbuf); tok_t* tok = peek_tok(tokbuf); ast_node_t* node = new_ast_ident_node(tok); @@ -22,7 +22,7 @@ ast_node_t* expect_pop_ident(tok_buf_t* tokbuf) { } ast_node_t* parse_type(parser_t* parser) { - tok_buf_t* tokbuf = &parser->tokbuf; + tok_stream_t* tokbuf = &parser->tokbuf; flush_peek_tok(tokbuf); tok_type_t ttype = peek_tok_type(tokbuf); data_type_t dtype; @@ -35,7 +35,7 @@ ast_node_t* parse_type(parser_t* parser) { case TOKEN_FLOAT: dtype = TYPE_FLOAT; break; case TOKEN_DOUBLE: dtype = TYPE_DOUBLE; break; default: - error("无效的类型说明符"); + LOG_ERROR("无效的类型说明符"); } ast_node_t* node = new_ast_node(); diff --git a/ccompiler/frontend/parser/parser.c b/ccompiler/frontend/parser/parser.c index bbeb3a7..4c98382 100644 --- a/ccompiler/frontend/parser/parser.c +++ b/ccompiler/frontend/parser/parser.c @@ -1,13 +1,16 @@ +#include #include "parser.h" #include "type.h" void init_parser(parser_t* parser, lexer_t* lexer, symtab_t* symtab) { + init_lib_core(); + parser->cur_node = NULL; parser->root = NULL; parser->lexer = lexer; parser->symtab = symtab; - init_tokbuf(&parser->tokbuf, lexer, (get_tokbuf_func)get_valid_token); + init_tokbuf(&parser->tokbuf, lexer, (tok_stream_get_func)get_valid_token); parser->tokbuf.cap = sizeof(parser->TokenBuffer) / sizeof(parser->TokenBuffer[0]); parser->tokbuf.buf = parser->TokenBuffer; } diff --git a/ccompiler/frontend/parser/parser.h b/ccompiler/frontend/parser/parser.h index ede7ceb..0b439e5 100644 --- a/ccompiler/frontend/parser/parser.h +++ b/ccompiler/frontend/parser/parser.h @@ -1,20 +1,19 @@ #ifndef __PARSER_H__ #define __PARSER_H__ -#include "../frontend.h" - #include "../lexer/lexer.h" +#include "ast.h" typedef struct lexer lexer_t; typedef struct symtab symtab_t; #define PARSER_MAX_TOKEN_QUEUE 16 typedef struct parser { - struct ASTNode* root; - struct ASTNode* cur_node; + ast_node_t* root; + ast_node_t* cur_node; lexer_t* lexer; symtab_t* symtab; - tok_buf_t tokbuf; + tok_stream_t tokbuf; tok_t TokenBuffer[PARSER_MAX_TOKEN_QUEUE]; int err_level; } parser_t; diff --git a/ccompiler/frontend/parser/symtab/symtab.c b/ccompiler/frontend/parser/symtab/symtab.c index 5cab0cc..8f14ce8 100644 --- a/ccompiler/frontend/parser/symtab/symtab.c +++ b/ccompiler/frontend/parser/symtab/symtab.c @@ -1,5 +1,6 @@ // symtab.c #include "../../frontend.h" +#include #include "scope.h" #include "symtab.h" @@ -24,7 +25,7 @@ void symtab_enter_scope(symtab_t* symtab) { void symtab_leave_scope(symtab_t* symtab) { Scope * scope = symtab->cur_scope; if (scope == NULL) { - error("cannot leave NULL scope or global scope"); + LOG_ERROR("cannot leave NULL scope or global scope"); } symtab->cur_scope = symtab->cur_scope->parent; scope_destroy(scope); @@ -35,7 +36,7 @@ void* symtab_add_symbol(symtab_t* symtab, const char* name, void* ast_node, int void* node = scope_lookup_current(scope, name); if (node != NULL) { if (!can_duplicate) { - error("duplicate symbol %s", name); + LOG_ERROR("duplicate symbol %s", name); } return node; } diff --git a/ccompiler/middleend/Makefile b/ccompiler/middleend/Makefile index 77d19c6..c75405e 100644 --- a/ccompiler/middleend/Makefile +++ b/ccompiler/middleend/Makefile @@ -1,20 +1,23 @@ # 编译器设置 CC = gcc AR = ar -CFLAGS = -g -Wall +CFLAGS = -g -Wall -I../.. + +IR_DIR = ./ir # 源文件列表 SRCS = \ - ir.c \ - ir_ast.c \ - ir_lib.c \ - ir_type.c + middleend.c \ + $(IR_DIR)/ir.c \ + $(IR_DIR)/ir_ast.c \ + $(IR_DIR)/ir_lib.c \ + $(IR_DIR)/ir_type.c # 生成目标文件列表 OBJS = $(SRCS:.c=.o) # 最终目标 -TARGET = libir.a +TARGET = libmiddleend.a all: $(TARGET) @@ -27,4 +30,4 @@ $(TARGET): $(OBJS) clean: rm -f $(OBJS) $(TARGET) -.PHONY: all clean \ No newline at end of file +.PHONY: all clean diff --git a/ccompiler/middleend/ir_ast.h b/ccompiler/middleend/ir/ir.c similarity index 100% rename from ccompiler/middleend/ir_ast.h rename to ccompiler/middleend/ir/ir.c diff --git a/ccompiler/middleend/ir.h b/ccompiler/middleend/ir/ir.h similarity index 94% rename from ccompiler/middleend/ir.h rename to ccompiler/middleend/ir/ir.h index 1263df1..9332a92 100644 --- a/ccompiler/middleend/ir.h +++ b/ccompiler/middleend/ir/ir.h @@ -2,9 +2,7 @@ #ifndef IR_CORE_H #define IR_CORE_H -#include "../../libcore/vector.h" -#include -#include +#include // 错误码定义 typedef enum { @@ -26,12 +24,12 @@ typedef struct { union { struct { struct ir_type *base; - size_t len; + rt_size_t len; } arr; struct { struct ir_type *ret; struct ir_type **params; - size_t param_cnt; + rt_size_t param_cnt; } func; }; } ir_type_t; @@ -151,9 +149,4 @@ struct ir_node { } data; }; -extern ir_prog_t prog; -struct ASTNode; -void gen_ir_from_ast(struct ASTNode* node); - - #endif // IR_CORE_H diff --git a/ccompiler/middleend/ir_ast.c b/ccompiler/middleend/ir/ir_ast.c similarity index 90% rename from ccompiler/middleend/ir_ast.c rename to ccompiler/middleend/ir/ir_ast.c index ab75f56..d3b0d40 100644 --- a/ccompiler/middleend/ir_ast.c +++ b/ccompiler/middleend/ir/ir_ast.c @@ -1,7 +1,8 @@ #include "ir.h" #include "ir_lib.h" #include "ir_type.h" -#include "../frontend/frontend.h" +#include "../../frontend/frontend.h" +#include "../../frontend/parser/ast.h" // 上下文结构,记录生成过程中的状态 typedef struct { @@ -10,6 +11,7 @@ typedef struct { } IRGenContext; IRGenContext ctx; ir_prog_t prog; +void _gen_ir_from_ast(ast_node_t* node); static void emit_instr(ir_bblock_t* block, ir_node_t* node) { if (block == NULL) block = ctx.cur_block; @@ -53,7 +55,7 @@ static ir_node_t* gen_ir_term(ast_node_t* node) { return call; } default: { - assert(0); + Panic("gen_ir_expr: unknown node type"); } } } @@ -164,10 +166,10 @@ static ir_node_t* gen_ir_expr(ast_node_t* node) { BINOP(IR_OP_GE); break; } case NT_AND_AND:// (expr) && (expr) - error("unimpliment"); + LOG_ERROR("unimpliment"); break; case NT_OR_OR:// (expr) || (expr) - error("unimpliment"); + LOG_ERROR("unimpliment"); break; case NT_NOT: { // ! (expr) @@ -189,7 +191,7 @@ static ir_node_t* gen_ir_expr(ast_node_t* node) { // case NT_COND: // (expr) ? (expr) : (expr) default: { // TODO self error msg - error("Unsupported IR generation for AST node type %d", node->type); + LOG_ERROR("Unsupported IR generation for AST node type %d", node->type); break; } } @@ -198,7 +200,7 @@ static ir_node_t* gen_ir_expr(ast_node_t* node) { } static void gen_ir_func(ast_node_t* node, ir_func_t* func) { - assert(node->type == NT_FUNC); + Assert(node->type == NT_FUNC); ir_bblock_t *entry = new_ir_bblock("entry"); vector_push(func->bblocks, entry); @@ -217,7 +219,7 @@ static void gen_ir_func(ast_node_t* node, ir_func_t* func) { decl->type = &type_i32; param->decl_val.data = decl; } - gen_ir_from_ast(node->func.body); + _gen_ir_from_ast(node->func.body); ctx = prev_ctx; } @@ -248,13 +250,13 @@ void gen_ir_jmp(ast_node_t* node) { // true block vector_push(ctx.cur_func->bblocks, trueb); ctx.cur_block = trueb; - gen_ir_from_ast(node->if_stmt.if_stmt); + _gen_ir_from_ast(node->if_stmt.if_stmt); // else block if (node->if_stmt.else_stmt != NULL) { vector_push(ctx.cur_func->bblocks, falseb); ctx.cur_block = falseb; - gen_ir_from_ast(node->if_stmt.else_stmt); + _gen_ir_from_ast(node->if_stmt.else_stmt); ir_node_t* jmp; ctx.cur_block = endb; @@ -285,7 +287,7 @@ void gen_ir_jmp(ast_node_t* node) { // Body: ir_node_t* jmp; ctx.cur_block = bodyb; - gen_ir_from_ast(node->while_stmt.body); + _gen_ir_from_ast(node->while_stmt.body); NEW_IR_JMP(jmp, entryb); emit_instr(NULL, jmp); @@ -304,7 +306,7 @@ void gen_ir_jmp(ast_node_t* node) { // Body: ctx.cur_block = bodyb; - gen_ir_from_ast(node->do_while_stmt.body); + _gen_ir_from_ast(node->do_while_stmt.body); ir_node_t* jmp; NEW_IR_JMP(jmp, entryb); emit_instr(NULL, jmp); @@ -324,7 +326,7 @@ void gen_ir_jmp(ast_node_t* node) { ir_bblock_t* endb = bblocks[2]; if (node->for_stmt.init) { - gen_ir_from_ast(node->for_stmt.init); + _gen_ir_from_ast(node->for_stmt.init); } ir_node_t* entry; NEW_IR_JMP(entry, entryb); @@ -342,7 +344,7 @@ void gen_ir_jmp(ast_node_t* node) { // Body: ctx.cur_block = bodyb; - gen_ir_from_ast(node->for_stmt.body); + _gen_ir_from_ast(node->for_stmt.body); if (node->for_stmt.iter) { gen_ir_expr(node->for_stmt.iter); } @@ -355,18 +357,21 @@ void gen_ir_jmp(ast_node_t* node) { break; } default: - error("ir jmp can't hit here"); + LOG_ERROR("ir jmp can't hit here"); } } -void gen_ir_from_ast(ast_node_t* node) { +ir_prog_t* gen_ir_from_ast(ast_node_t* root) { + Assert(root->type == NT_ROOT); + for (int i = 0; i < root->root.children.size; i ++) { + _gen_ir_from_ast(root->root.children.data[i]); + } + // _gen_ir_from_ast(root); + return &prog; +} + +void _gen_ir_from_ast(ast_node_t* node) { switch (node->type) { - case NT_ROOT: { - for (int i = 0; i < node->root.children.size; i ++) { - gen_ir_from_ast(node->root.children.data[i]); - } - break; - } case NT_DECL_FUNC: { ir_func_t* func = new_ir_func(node->decl_func.name->syms.tok.val.str, &type_i32); if (node->decl_func.def == NULL) { @@ -398,12 +403,12 @@ void gen_ir_from_ast(ast_node_t* node) { break; } case NT_STMT_BLOCK: { - gen_ir_from_ast(node->block_stmt.block); + _gen_ir_from_ast(node->block_stmt.block); break; } case NT_BLOCK: { for (int i = 0; i < node->block.children.size; i ++) { - gen_ir_from_ast(node->block.children.data[i]); + _gen_ir_from_ast(node->block.children.data[i]); } break; } @@ -420,7 +425,7 @@ void gen_ir_from_ast(ast_node_t* node) { ir->type = &type_i32; node->decl_val.data = ir; if (node->decl_val.expr_stmt != NULL) { - gen_ir_from_ast(node->decl_val.expr_stmt); + _gen_ir_from_ast(node->decl_val.expr_stmt); } break; } @@ -433,7 +438,7 @@ void gen_ir_from_ast(ast_node_t* node) { } default: // TODO: 错误处理 - error("unknown node type"); + LOG_ERROR("unknown node type"); break; } } diff --git a/ccompiler/middleend/ir/ir_ast.h b/ccompiler/middleend/ir/ir_ast.h new file mode 100644 index 0000000..356fd03 --- /dev/null +++ b/ccompiler/middleend/ir/ir_ast.h @@ -0,0 +1,7 @@ +#ifndef __IR_AST_H__ +#define __IR_AST_H__ + +#include "ir.h" +ir_prog_t* gen_ir_from_ast(ast_node_t* node); + +#endif // diff --git a/ccompiler/middleend/ir/ir_dump.c b/ccompiler/middleend/ir/ir_dump.c new file mode 100644 index 0000000..df1ca95 --- /dev/null +++ b/ccompiler/middleend/ir/ir_dump.c @@ -0,0 +1,76 @@ +#include "ir.h" +#include "ir_lib.h" +#include "ir_type.h" +#include +#include + +typedef struct ir_dump { + FILE* fp; +} ir_dump_t; + + +void dump_ir_node(ir_node_t* node, ir_dump_t* dump) { + fprintf(dump->fp, "%%%p", node); + switch (node->tag) { + case IR_NODE_ALLOC: { + node->type = NULL; + // fprintf(dump->fp, "%p\n", ); + break; + } + case IR_NODE_BRANCH: { + node->data.branch.cond = NULL; + node->data.branch.true_bblock = NULL; + node->data.branch.false_bblock = NULL; + break; + } + case IR_NODE_CALL: { + vector_init(node->data.call.args); + node->data.call.callee = NULL; + break; + } + case IR_NODE_CONST_INT: { + node->data.const_int.val = 0; + break; + } + case IR_NODE_JUMP: { + node->data.jump.target_bblock = NULL; + break; + } + case IR_NODE_LOAD: { + node->data.load.target = NULL; + break; + } + case IR_NODE_STORE: { + node->data.store.target = NULL; + node->data.store.value = NULL; + break; + } + case IR_NODE_OP: { + node->data.op.op = 0; + node->data.op.lhs = NULL; + node->data.op.rhs = NULL; + break; + } + case IR_NODE_RET: { + node->data.ret.ret_val = NULL; + break; + } + case IR_NODE_GET_PTR: { + } + default: { + assert(0); + } + } +} + +void dump_ir_bblock(ir_bblock_t* block) { + +} + +void dump_ir_func(ir_func_t* func) { + +} + +void dump_ir_prog(ir_prog_t* prog) { + +} diff --git a/ccompiler/middleend/ir_lib.c b/ccompiler/middleend/ir/ir_lib.c similarity index 98% rename from ccompiler/middleend/ir_lib.c rename to ccompiler/middleend/ir/ir_lib.c index a6b3614..a72019e 100644 --- a/ccompiler/middleend/ir_lib.c +++ b/ccompiler/middleend/ir/ir_lib.c @@ -77,10 +77,6 @@ ir_node_t* new_ir_node(const char* name, ir_node_tag_t tag) { return node; } -void dump_ir_node(ir_node_t* node) { - -} - void free_irnode() { } diff --git a/ccompiler/middleend/ir_lib.h b/ccompiler/middleend/ir/ir_lib.h similarity index 100% rename from ccompiler/middleend/ir_lib.h rename to ccompiler/middleend/ir/ir_lib.h diff --git a/ccompiler/middleend/ir_type.c b/ccompiler/middleend/ir/ir_type.c similarity index 100% rename from ccompiler/middleend/ir_type.c rename to ccompiler/middleend/ir/ir_type.c diff --git a/ccompiler/middleend/ir_type.h b/ccompiler/middleend/ir/ir_type.h similarity index 100% rename from ccompiler/middleend/ir_type.h rename to ccompiler/middleend/ir/ir_type.h diff --git a/ccompiler/middleend/middleend.c b/ccompiler/middleend/middleend.c new file mode 100644 index 0000000..e69de29 diff --git a/ccompiler/middleend/middleend.h b/ccompiler/middleend/middleend.h new file mode 100644 index 0000000..21966d6 --- /dev/null +++ b/ccompiler/middleend/middleend.h @@ -0,0 +1,7 @@ +#ifndef __SMCC_MIDDLEEND_H__ +#define __SMCC_MIDDLEEND_H__ + +#include "ir/ir.h" +#include "ir/ir_ast.h" + +#endif // __SMCC_MIDDLEEND_H__ diff --git a/lib/Makefile b/lib/Makefile new file mode 100644 index 0000000..1e5ab6d --- /dev/null +++ b/lib/Makefile @@ -0,0 +1,35 @@ +# 编译器设置 +CC = gcc +AR = ar +CFLAGS = -g -Wall -I.. + +# 源文件路径 +RT_DIR = ./rt +LOG_DIR = ./rt/log + +# 源文件列表 +SRCS = \ + $(RT_DIR)/std/rt_std.c \ + ./core.c \ + $(RT_DIR)/rt.c \ + $(RT_DIR)/rt_alloc.c \ + $(LOG_DIR)/log.c + +# 生成目标文件列表 +OBJS = $(SRCS:.c=.o) + +# 最终目标 +TARGET = libcore.a + +all: $(TARGET) + +$(TARGET): $(OBJS) + $(AR) rcs $@ $^ + +%.o: %.c + $(CC) $(CFLAGS) -c -o $@ $< + +clean: + rm -f $(OBJS) $(TARGET) + +.PHONY: all clean diff --git a/libcore/acutest.h b/lib/acutest.h similarity index 100% rename from libcore/acutest.h rename to lib/acutest.h diff --git a/lib/core.c b/lib/core.c new file mode 100644 index 0000000..72593e8 --- /dev/null +++ b/lib/core.c @@ -0,0 +1,10 @@ +#include "core.h" + +void init_lib_core() { + static int init = 0; + if (init) return; + init_rt(); + + init += 1; + Assert(init == 1); +} diff --git a/lib/core.h b/lib/core.h new file mode 100644 index 0000000..4d3c44f --- /dev/null +++ b/lib/core.h @@ -0,0 +1,9 @@ +#ifndef __SMCC_LIB_CORE_H__ +#define __SMCC_LIB_CORE_H__ + +#include "rt/rt.h" + +// You MUST BE call this by the start +void init_lib_core(); + +#endif // __SMCC_LIB_CORE_H__ diff --git a/lib/rt/log/color.h b/lib/rt/log/color.h new file mode 100644 index 0000000..c7bc46a --- /dev/null +++ b/lib/rt/log/color.h @@ -0,0 +1,33 @@ +#ifndef __SMCC_TERMINAL_COLOR_H__ +#define __SMCC_TERMINAL_COLOR_H__ + +#define ANSI_FG_BLACK "\33[30m" +#define ANSI_FG_RED "\33[31m" +#define ANSI_FG_GREEN "\33[32m" +#define ANSI_FG_YELLOW "\33[33m" +#define ANSI_FG_BLUE "\33[34m" +#define ANSI_FG_MAGENTA "\33[35m" +#define ANSI_FG_CYAN "\33[36m" +#define ANSI_FG_WHITE "\33[37m" + +#define ANSI_BG_BLACK "\33[40m" +#define ANSI_BG_RED "\33[41m" +#define ANSI_BG_GREEN "\33[42m" +#define ANSI_BG_YELLOW "\33[43m" +#define ANSI_BG_BLUE "\33[44m" +#define ANSI_BG_MAGENTA "\33[35m" +#define ANSI_BG_CYAN "\33[46m" +#define ANSI_BG_WHITE "\33[47m" + +#define ANSI_UNDERLINED "\33[4m" +#define ANSI_BOLD "\33[1m" +#define ANSI_NONE "\33[0m" + +// Maybe Some Terminal Doesn't Support Color +#ifndef ANSI_FMT_DISABLE +#define ANSI_FMT(str, fmt) fmt str ANSI_NONE +#else +#define ANSI_FMT(str, fmt) str +#endif + +#endif diff --git a/lib/rt/log/log.c b/lib/rt/log/log.c new file mode 100644 index 0000000..b704fe3 --- /dev/null +++ b/lib/rt/log/log.c @@ -0,0 +1,65 @@ +#include "log.h" + +typedef void (*log_handler)( + log_level_t level, + const char* module, + const char* file, + int line, + const char* message +); + +static void default_handler(log_level_t level, const char* module, const char* file, int line, const char* message) { + if (!rt_stderr) return; + const char* level_str; + switch (level) { + case LOG_LEVEL_DEBUG: level_str = "DEBUG"; break; + case LOG_LEVEL_INFO: level_str = "INFO "; break; + case LOG_LEVEL_WARN: level_str = "WARN "; break; + case LOG_LEVEL_ERROR: level_str = "ERROR"; break; + case LOG_LEVEL_FATAL: level_str = "FATAL"; break; + case LOG_LEVEL_TRACE: level_str = "TRACE"; break; + default: level_str = "NOTSET"; break; + } + +#ifndef __LOG_NO_COLOR__ + const char* color_code = ANSI_NONE; + switch (level) { + case LOG_LEVEL_DEBUG: color_code = ANSI_FG_CYAN; break; + case LOG_LEVEL_INFO: color_code = ANSI_FG_GREEN; break; + case LOG_LEVEL_TRACE: color_code = ANSI_FG_BLUE; break; + case LOG_LEVEL_WARN: color_code = ANSI_FG_YELLOW; break; + case LOG_LEVEL_ERROR: color_code = ANSI_FG_RED; break; + case LOG_LEVEL_FATAL: color_code = ANSI_FG_RED ANSI_UNDERLINED; break; // 增强对比度 + default: color_code = ANSI_NONE; + } + + rt.fprintf(rt_stderr, ANSI_BOLD "%s[%s] - %s - %s:%d | %s" ANSI_NONE "\n", color_code, + level_str, module, file, line, message); +#else + rt.fprintf(rt_stderr, "[%s] %s:%d | %s: %s\n", + level_str, file, line, module, message); +#endif + if (level & LOG_LEVEL_FATAL) { + rt.exit(-LOG_LEVEL_FATAL); + } +} + +static logger_t root_logger = { + .name = "root", + .level = LOG_LEVEL_ALL, + .handler = default_handler, +}; + +logger_t* log_get(const char* name) { + return &root_logger; +} + +void log_set_level(logger_t* logger, log_level_t level) { + if (logger) logger->level = level; + else root_logger.level = level; +} + +void log_set_handler(logger_t* logger, log_handler handler) { + if (logger) logger->handler = handler; + else root_logger.handler = handler; +} diff --git a/lib/rt/log/log.h b/lib/rt/log/log.h new file mode 100644 index 0000000..ccb8028 --- /dev/null +++ b/lib/rt/log/log.h @@ -0,0 +1,75 @@ +#ifndef __SMCC_LOG_H__ +#define __SMCC_LOG_H__ + +#include "../std/rt_api_def.h" +#include "color.h" + +typedef enum log_level { + LOG_LEVEL_NOTSET = 0, + LOG_LEVEL_DEBUG = 1 << 0, + LOG_LEVEL_INFO = 1 << 1, + LOG_LEVEL_WARN = 1 << 2, + LOG_LEVEL_ERROR = 1 << 3, + LOG_LEVEL_FATAL = 1 << 4, + + LOG_LEVEL_TRACE = 1 << 5, + LOG_LEVEL_ALL = 0xFF, +} log_level_t; + +typedef void (*log_handler)( + log_level_t level, + const char* module, + const char* file, + int line, + const char* message +); + +#ifndef LOGGER_MAX_BUF_SIZE +#define LOGGER_MAX_BUF_SIZE 256 +#endif + +typedef struct logger { + const char* name; + log_level_t level; + log_handler handler; + char buf[LOGGER_MAX_BUF_SIZE]; +} logger_t; + +logger_t* log_get(const char* name); +void log_set_level(logger_t* logger, log_level_t level); +void log_set_handler(logger_t* logger, log_handler handler); + +#ifndef LOG_MAX_MAROC_BUF_SIZE +#define LOG_MAX_MAROC_BUF_SIZE LOGGER_MAX_BUF_SIZE +#endif +#define _LOG(_level_, _msg_, ...) \ + do { \ + logger_t* _logger = log_get(NULL); \ + if (_logger && _logger->handler && (_logger->level & (_level_))) { \ + rt.snprintf(_logger->buf, sizeof(_logger->buf), (_msg_), ##__VA_ARGS__); \ + _logger->handler((_level_), _logger->name, __FILE__, __LINE__, _logger->buf); \ + } \ + } while(0) + +#define LOG_NOTSET(...) _LOG(LOG_LEVEL_NOTSET, __VA_ARGS__) +#define LOG_DEBUG(...) _LOG(LOG_LEVEL_DEBUG, __VA_ARGS__) +#define LOG_INFO(...) _LOG(LOG_LEVEL_INFO, __VA_ARGS__) +#define LOG_WARN(...) _LOG(LOG_LEVEL_WARN, __VA_ARGS__) +#define LOG_ERROR(...) _LOG(LOG_LEVEL_ERROR, __VA_ARGS__) +#define LOG_FATAL(...) _LOG(LOG_LEVEL_FATAL, __VA_ARGS__) +#define LOG_TRACE(...) _LOG(LOG_LEVEL_TRACE, __VA_ARGS__) + + +#define _Assert(cond, ...) \ + do { \ + if (!(cond)) { \ + LOG_FATAL(__VA_ARGS__); \ + } \ + } while (0) +#define AssertFmt(cond, format, ...) _Assert(cond, "Assertion Failure: " format, ## __VA_ARGS__) +#define PanicFmt(format, ...) _Assert(0, "Panic: " format, ## __VA_ARGS__) +#define Assert(cond) AssertFmt(cond, "cond is `" SMCC_STR(cond) "`") +#define Panic(...) PanicFmt(__VA_ARGS__) +#define TODO() PanicFmt("TODO please implement me") + +#endif diff --git a/lib/rt/rt.c b/lib/rt/rt.c new file mode 100644 index 0000000..3d20f45 --- /dev/null +++ b/lib/rt/rt.c @@ -0,0 +1,10 @@ +#include "rt.h" + +void init_rt() { +// TODO Choice OS +#ifndef __SMCC_NO_OS_STD__ + #include "std/rt_std.h" + init_rt_std(); +#endif + return; +} diff --git a/lib/rt/rt.h b/lib/rt/rt.h new file mode 100644 index 0000000..8c2d0ee --- /dev/null +++ b/lib/rt/rt.h @@ -0,0 +1,18 @@ +#ifndef __SMCC_RT_H__ +#define __SMCC_RT_H__ + +#include "std/rt_api_def.h" +#include "std/rt_type.h" +#include "log/log.h" +#include "rt_alloc.h" +#include "rt_string.h" + +void init_rt(); + +// define +#define _SMCC_STR(str) #str +#define SMCC_STR(str) _SMCC_STR(str) + +#define SMCC_ARRLEN(arr) (sizeof(arr) / sizeof(arr[0])) + +#endif // __SMCC_RT_H__ diff --git a/lib/rt/rt_alloc.c b/lib/rt/rt_alloc.c new file mode 100644 index 0000000..5a3f863 --- /dev/null +++ b/lib/rt/rt_alloc.c @@ -0,0 +1,135 @@ +#include "rt_alloc.h" + +#define ALLOCATOR_PAGE_SIZE (4096) + +/* Simple / Static Allocator */ + +void* salloc_alloc(int size) { + // TODO do some trace + return rt._malloc(size); +} + +void* salloc_realloc(void* ptr, int size) { + return rt._realloc(ptr, size); +} + +void salloc_free(void* ptr) { + // TODO do some trace + rt._free(ptr); +} + +/* Fixed Allocator */ + +#define PAGE_ALIGN(size) (((size) + ALLOCATOR_PAGE_SIZE -1) & ~(ALLOCATOR_PAGE_SIZE-1)) + +void falloc_init(fixed_alloc_t* fa, int fixed_size, int init_blocks) { + fa->free_list = NULL; + fa->page_list = NULL; + + // 确保块大小至少能存放指针(用于空闲链表) + const int min_size = sizeof(void*); + fa->block_size = (fixed_size < min_size) ? min_size : + (fixed_size + 15) & ~15; // 16字节对齐 + + // 计算每页块数(优化缓存利用率) + const int page_size = ALLOCATOR_PAGE_SIZE - sizeof(void*); + fa->blocks_per_page = page_size / fa->block_size; + + // TODO copy paste 需要使用函数抽象 申请过程 + // 预分配初始页 + void* page = salloc_alloc(PAGE_ALIGN(fa->block_size * init_blocks)); + unsigned char* p = (unsigned char*)page; + for (int i = 0; i < init_blocks; ++i) { + void** block = (void**)p; + *block = fa->free_list; + fa->free_list = block; + p += fa->block_size; + } + + *(void**)page = fa->page_list; + fa->page_list = page; +} + +void* falloc_alloc(fixed_alloc_t* fa) { + if (!fa->free_list) { + // 分配新页(带页头保存链表指针) + void* page = salloc_alloc(ALLOCATOR_PAGE_SIZE); + unsigned char* p = (unsigned char*)page + sizeof(void*); + + // 链接新页块到空闲链表 + for (int i = 0; i < fa->blocks_per_page; ++i) { + void** block = (void**)p; + *block = fa->free_list; + fa->free_list = block; + p += fa->block_size; + } + + *(void**)page = fa->page_list; + fa->page_list = page; + } + + void* block = fa->free_list; + fa->free_list = *(void**)block; + return (void*)((unsigned char*)block + sizeof(void*)); // 跳过链表指针 +} + +void falloc_free(fixed_alloc_t* fa, void* ptr) { + if (!fa || !ptr) return; + + void** block = (void**)((u8_t*)ptr - sizeof(void*)); + *block = fa->free_list; + fa->free_list = block; +} + +void falloc_destroy(fixed_alloc_t* fa) { + if (!fa) return; + + // 逆向释放所有内存页(保持地址连续性) + void* current_page = fa->page_list; + while (current_page) { + void* next_page = *(void**)current_page; // 页头保存了链表指针 + salloc_free(current_page); + current_page = next_page; + } + + // 防御性清零(防止悬垂指针) + fa->free_list = NULL; + fa->blocks_per_page = 0; + fa->block_size = 0; + fa->page_list = NULL; +} + +/* Long Allocator */ + +void lalloc_init(long_alloc_t* la) { + la->current = NULL; + la->block_size = ALLOCATOR_PAGE_SIZE; // 初始块大小 +} + +void* lalloc_alloc(long_alloc_t* la, int size) { + size = (size + 15) & ~15; // 16字节对齐 + + if (!la->current || (la->current->used + size) > la->block_size) { + int new_size = la->block_size; + if (new_size < size + sizeof(long_block_t)) + new_size = size + sizeof(long_block_t); + + long_block_t* new_block = (long_block_t*)salloc_alloc(new_size); + new_block->next = la->current; + new_block->used = sizeof(long_block_t); + la->current = new_block; + la->block_size = new_size; + } + + void* ptr = (unsigned char*)la->current + la->current->used; + la->current->used += size; + return ptr; +} + +void lalloc_destroy(long_alloc_t* la) { + while (la->current) { + long_block_t* prev = la->current->next; + salloc_free(la->current); + la->current = prev; + } +} diff --git a/lib/rt/rt_alloc.h b/lib/rt/rt_alloc.h new file mode 100644 index 0000000..7e12537 --- /dev/null +++ b/lib/rt/rt_alloc.h @@ -0,0 +1,36 @@ +#ifndef __SMCC_RT_ALLOC_H__ +#define __SMCC_RT_ALLOC_H__ + +#include "std/rt_api_def.h" +// Simple or Static Allocator + +void* salloc_alloc(int size); +void* salloc_realloc(void* ptr, int size); +void salloc_free(void* ptr); + +typedef struct fixed_alloc { + void* page_list; + void* free_list; + int block_size; + int blocks_per_page; +} fixed_alloc_t; +void falloc_init(fixed_alloc_t* fa, int fixed_size, int init_size); +void* falloc_alloc(fixed_alloc_t* fa); +void falloc_free(fixed_alloc_t* fa, void* ptr); +void falloc_destroy(fixed_alloc_t* fa); + +typedef struct long_block { + struct long_block* next; + int used; +} long_block_t; + +typedef struct long_alloc { + long_block_t* current; + int block_size; +} long_alloc_t; +void lalloc_init(long_alloc_t* la); +void* lalloc_alloc(long_alloc_t* la, int size); +void lalloc_free(long_alloc_t* la, void* ptr); +void lalloc_destroy(long_alloc_t* la); + +#endif diff --git a/lib/rt/rt_string.c b/lib/rt/rt_string.c new file mode 100644 index 0000000..159a928 --- /dev/null +++ b/lib/rt/rt_string.c @@ -0,0 +1,49 @@ +#include "rt_string.h" + +int rt_memcmp(const void* s1, const void* s2, rt_size_t n) { + const unsigned char *p1 = s1, *p2 = s2; + for (rt_size_t i = 0; i < n; ++i) { + if (p1[i] != p2[i]) + return p1[i] - p2[i]; + } + return 0; +} + +int rt_strcmp(const char* s1, const char* s2) { + while (*s1 && *s2 && (*s1 == *s2)) { + s1++; + s2++; + } + return *(const unsigned char*)s1 - *(const unsigned char*)s2; +} + +void* rt_memcpy(void* restrict dest, const void* restrict src, rt_size_t n) { + u8_t* d = dest; + const u8_t* s = src; + for (rt_size_t i = 0; i < n; ++i) + d[i] = s[i]; + return dest; +} + +void* rt_memset(void* s, int c, rt_size_t n) { + u8_t* p = s; + for (rt_size_t i = 0; i < n; ++i) + p[i] = (u8_t)c; + return s; +} + +rt_size_t rt_strlen(const char* s) { + const char* p = s; + while (*p) p++; + return p - s; +} + +/* strhash - 字符串哈希(用于符号表) */ +u32_t rt_strhash(const char* s) { + u32_t hash = 2166136261u; // FNV-1a偏移基础值 + while (*s) { + hash ^= *s++; + hash *= 16777619u; + } + return hash; +} diff --git a/lib/rt/rt_string.h b/lib/rt/rt_string.h new file mode 100644 index 0000000..dd4d30e --- /dev/null +++ b/lib/rt/rt_string.h @@ -0,0 +1,15 @@ +#ifndef __SMCC_RT_STRING_H__ +#define __SMCC_RT_STRING_H__ + +#include "std/rt_api_def.h" + +int rt_memcmp(const void* s1, const void* s2, rt_size_t n); +int rt_strcmp(const char* s1, const char* s2); + +void* rt_memcpy(void* restrict dest, const void* restrict src, rt_size_t n); +void* rt_memset(void* s, int c, rt_size_t n); + +rt_size_t rt_strlen(const char* s); +u32_t rt_strhash(const char* s); + +#endif // __SMCC_RT_STRING_H__ diff --git a/lib/rt/std/rt_api_def.h b/lib/rt/std/rt_api_def.h new file mode 100644 index 0000000..7b98053 --- /dev/null +++ b/lib/rt/std/rt_api_def.h @@ -0,0 +1,64 @@ +#ifndef __SMCC_RT_API_DEF_H__ +#define __SMCC_RT_API_DEF_H__ + +#include "rt_type.h" + +#ifndef __RT_SIZE_TYPE__ +#define __RT_SIZE_TYPE__ +typedef usz_t rt_size_t; +#endif +typedef void* (*rt_malloc)(rt_size_t size); +typedef void (*rt_free)(void* ptr); +typedef void (*rt_exit)(int code); + +#ifndef __RT_FILE_TYPE__ +#define __RT_FILE_TYPE__ +typedef void* rt_file_t; +#endif +extern rt_file_t rt_stdin; +extern rt_file_t rt_stdout; +extern rt_file_t rt_stderr; +typedef rt_file_t (*rt_fopen_t)(const char* file_name, const char* mode); +typedef int (*rt_fflush_t)(rt_file_t*file); +typedef int (*rt_fclose_t)(rt_file_t file); +typedef int (*rt_freads_t)(void * dst_buf, rt_size_t dst_size, rt_size_t elem_size, rt_size_t count, rt_file_t file); +typedef int (*rt_fwrite_t)(const void * buf, rt_size_t size, rt_size_t count, rt_file_t file); + +typedef int (*rt_fprintf_t)(void * file, const char *format, ...); +typedef int (*rt_snprintf_t)(char * stream, rt_size_t n, const char * format, ...); +typedef void* (*rt_realloc_t)(void *memory, rt_size_t new_size); + +typedef struct smcc_rt { + rt_malloc _malloc; + rt_free _free; + rt_exit exit; + + rt_fopen_t fopen; + rt_fflush_t fflush; + rt_fclose_t fclose; + rt_freads_t freads; + rt_fwrite_t fwrite; + + // Optional useful runtime + rt_fprintf_t fprintf; + rt_snprintf_t snprintf; + rt_realloc_t _realloc; +} smcc_rt_t; + +extern const smcc_rt_t rt; + +// #ifndef NULL +// #ifdef __cplusplus +// #ifndef _WIN64 +// #define NULL 0 +// #else +// #define NULL 0LL +// #endif /* W64 */ +// #else +// #define NULL ((void *)0) +// #endif +// #endif + +#define NULL ((void *)0) + +#endif diff --git a/lib/rt/std/rt_std.c b/lib/rt/std/rt_std.c new file mode 100644 index 0000000..2f47bbb --- /dev/null +++ b/lib/rt/std/rt_std.c @@ -0,0 +1,32 @@ +#include +#include +#include +#include + +#include "rt_api_def.h" + +const smcc_rt_t rt = { + ._malloc = (rt_malloc)malloc, + ._free = (rt_free)free, + .exit = (rt_exit)exit, + + .fopen = (rt_fopen_t)fopen, + .fflush = (rt_fflush_t)fflush, + .fclose = (rt_fclose_t)fclose, + .freads = (rt_freads_t)fread_s, + .fwrite = (rt_fwrite_t)fwrite, + + ._realloc = (rt_realloc_t)realloc, + .fprintf = (rt_fprintf_t)fprintf, + .snprintf = (rt_snprintf_t)snprintf, +}; + +rt_file_t rt_stdin; +rt_file_t rt_stdout; +rt_file_t rt_stderr; + +void init_rt_std() { + rt_stdin = stdin; + rt_stdout = stdout; + rt_stderr = stderr; +} diff --git a/lib/rt/std/rt_std.h b/lib/rt/std/rt_std.h new file mode 100644 index 0000000..45644de --- /dev/null +++ b/lib/rt/std/rt_std.h @@ -0,0 +1,6 @@ +#ifndef __SMCC_RT_STD_H__ +#define __SMCC_RT_STD_H__ + +void init_rt_std(); + +#endif diff --git a/lib/rt/std/rt_type.h b/lib/rt/std/rt_type.h new file mode 100644 index 0000000..13d2126 --- /dev/null +++ b/lib/rt/std/rt_type.h @@ -0,0 +1,28 @@ +#ifndef __SMCC_RT_TYPE_H__ +#define __SMCC_RT_TYPE_H__ + +#include + +typedef int8_t i8_t; +typedef int16_t i16_t; +typedef int32_t i32_t; +typedef int64_t i64_t; + +typedef uint8_t u8_t; +typedef uint16_t u16_t; +typedef uint32_t u32_t; +typedef uint64_t u64_t; + +typedef float f32_t; +typedef double f64_t; + +typedef intptr_t iptr_t; +typedef uintptr_t uptr_t; + +typedef size_t usz_t; +typedef ssize_t isz_t; + +// typedef u32_t uw_t; +// typedef i32_t iw_t; + +#endif diff --git a/lib/test/test.py b/lib/test/test.py new file mode 100644 index 0000000..e69de29 diff --git a/lib/test/test_alloc..c b/lib/test/test_alloc..c new file mode 100644 index 0000000..e69de29 diff --git a/lib/test/test_log.c b/lib/test/test_log.c new file mode 100644 index 0000000..293de70 --- /dev/null +++ b/lib/test/test_log.c @@ -0,0 +1,15 @@ +#include + +int main(void) { + // make -C .. + // gcc -g -Wall -I../.. test_log.c -L.. -lcore -o test_log + // ./test_log + init_lib_core(); + + LOG_NOTSET("Log notset"); + LOG_DEBUG("Log debug"); + LOG_INFO("Log info"); + LOG_WARN("Log warn"); + LOG_ERROR("Log error"); + LOG_FATAL("Log fatal"); +} diff --git a/lib/utils/ds/hashtable.c b/lib/utils/ds/hashtable.c new file mode 100644 index 0000000..c61a120 --- /dev/null +++ b/lib/utils/ds/hashtable.c @@ -0,0 +1,142 @@ +#include "hashtable.h" + +#define LOAD_FACTOR 0.75f +// 素数表用于桶扩容(最后一个元素为最大允许容量) +static const int PRIME_CAPACITIES[] = { + 11, 23, 47, 97, 193, 389, 769, 1543, 3079, + 6151, 12289, 24593, 49157, 98317, 196613, 393241, + 786433, 1572869, 3145739, 6291469, 12582917, 25165843 +}; + +// 私有函数声明 +static u32_t calc_hash(const char* str, int len); +static void rehash(hash_table_t* ht); + +hash_table_t* new_hash_table(int init_size, int max_cap) { + hash_table_t* ht = salloc_alloc(sizeof(hash_table_t)); + hash_table_init(ht, init_size, max_cap); + return ht; +} + +static inline get_real_size(int size) { + // 查找第一个不小于size的素数容量 + int cap_idx = 0; + if (size < 0) { + return PRIME_CAPACITIES[SMCC_ARRLEN(PRIME_CAPACITIES)-1]; + } + while (PRIME_CAPACITIES[cap_idx] < size && cap_idx < SMCC_ARRLEN(PRIME_CAPACITIES)-1) { + cap_idx++; + } + return PRIME_CAPACITIES[cap_idx]; +} + +void hash_table_init(hash_table_t* ht, int init_size, int max_cap) { + // 限制最大容量索引 + ht->max_cap = get_real_size(max_cap); + // 应用实际容量 + ht->cap = get_real_size(init_size); + ht->size = 0; + ht->buckets = NULL; + ht->buckets = salloc_realloc(ht->buckets, sizeof(hash_node_t*) * ht->cap); +} + +void hash_table_insert(hash_table_t* ht, const char* str, int len) { + // 自动扩容检查 + if (ht->size >= ht->cap * LOAD_FACTOR && ht->cap < ht->max_cap) { + rehash(ht); + } + + if (ht->size >= ht->cap) { + LOG_TRACE("Hash table size exceeds maximum capacity. Consider increasing max_capacity."); + } + + // 计算哈希值 + u32_t hash = calc_hash(str, len); + int bucket_idx = hash % ht->cap; + + // 检查重复 + hash_node_t* node = ht->buckets[bucket_idx]; + while (node) { + if (node->hash == hash && + node->len == len && + memcmp(node->str, str, len) == 0) { + return; // 已存在 + } + node = node->next; + } + + // 创建新节点 + hash_node_t* new_node = salloc_alloc(sizeof(hash_node_t)); + new_node->str = str; + new_node->len = len; + new_node->hash = hash; + new_node->next = ht->buckets[bucket_idx]; + ht->buckets[bucket_idx] = new_node; + ht->size++; +} + +hash_node_t* hash_table_find(hash_table_t* ht, const char* str, int len) { + u32_t hash = calc_hash(str, len); + int bucket_idx = hash % ht->cap; + + hash_node_t* node = ht->buckets[bucket_idx]; + while (node) { + if (node->hash == hash && + node->len == len && + memcmp(node->str, str, len) == 0) { + return node; + } + node = node->next; + } + return NULL; +} + +static void rehash(hash_table_t* ht) { + int old_cap = ht->cap; + hash_node_t** old_buckets = ht->buckets; + + // 查找下一个素数容量 + int new_cap_idx = 0; + while (PRIME_CAPACITIES[new_cap_idx] <= old_cap && + new_cap_idx < ht->max_cap) { + new_cap_idx++; + } + ht->cap = PRIME_CAPACITIES[new_cap_idx]; + + // 分配新桶数组 + ht->buckets = salloc_alloc(sizeof(hash_node_t*) * ht->cap); + memset(ht->buckets, 0, sizeof(hash_node_t*) * ht->cap); + + // 重新哈希所有节点 + for (int i = 0; i < old_cap; i++) { + hash_node_t* node = old_buckets[i]; + while (node) { + hash_node_t* next = node->next; + int new_bucket = node->hash % ht->cap; + node->next = ht->buckets[new_bucket]; + ht->buckets[new_bucket] = node; + node = next; + } + } + + salloc_free(old_buckets); +} + +static u32_t calc_hash(const char* str, int len) { + // 使用与HASH_FNV_1A宏一致的算法 + rt_strhash(str); +} + +void hash_table_destroy(hash_table_t* ht) { + for (int i = 0; i < ht->cap; i++) { + hash_node_t* node = ht->buckets[i]; + while (node) { + hash_node_t* next = node->next; + salloc_free(node); + node = next; + } + } + salloc_free(ht->buckets); + ht->buckets = NULL; + ht->size = ht->cap = 0; +} \ No newline at end of file diff --git a/lib/utils/ds/hashtable.h b/lib/utils/ds/hashtable.h new file mode 100644 index 0000000..6c771f4 --- /dev/null +++ b/lib/utils/ds/hashtable.h @@ -0,0 +1,27 @@ +#ifndef __SMCC_HASHTABLE_H__ +#define __SMCC_HASHTABLE_H__ + +#include + +typedef struct hash_node { + const char* str; + int len; + u32_t hash; + struct hash_node* next; +} hash_node_t; + +typedef struct hash_table { + hash_node_t** buckets; + int size; + int cap; + int max_cap; +} hash_table_t; + +hash_table_t* new_hash_table(int init_size, int max_cap); +void hash_table_init(hash_table_t* ht, int init_size, int max_cap); +void hash_table_destroy(hash_table_t* ht); + +void hash_table_insert(hash_table_t* ht, const char* str, int len); +hash_node_t* hash_table_find(hash_table_t* ht, const char* str, int len); + +#endif // __SMCC_HASHTABLE_H__ diff --git a/lib/utils/ds/kllist.h b/lib/utils/ds/kllist.h new file mode 100644 index 0000000..d6c9d59 --- /dev/null +++ b/lib/utils/ds/kllist.h @@ -0,0 +1,158 @@ +/** + * kllist.h is a list implement by linux kernel list + * @link https://njusecourse.feishu.cn/wiki/I8vkw2zkwiEInUkujTJc7zzOnwf + * @link https://kernelnewlbies.org/FAQ/LinkedLists + * @link https://lwn.net/Articles/887097/ + * @link https://liuluheng.github.io/wiki/public_html/Embedded-System/kernel/list-and-hlist.html + */ + +#ifndef __KLLIST_H__ +#define __KLLIST_H__ + +#ifndef NULL +#define NULL (0) +#define __NULL_KLIST_DEFINED__ +#endif + +#ifndef container_of +// Magic: https://radek.io/posts/magical-container_of-macro/ +// StackOverflow: https://stackoverflow.com/q/15832301/1833118 +#ifdef __GNUC__ +#define container_of(ptr, type, member) ({ \ + const typeof( ((type *)0)->member ) *__mptr = (ptr); \ + (type *)( (char *)__mptr - offsetof(type,member) );}) +#else +#define container_of(ptr, type, member) ({ \ + const void *__mptr = (ptr); \ + (type *)( (char *)__mptr - offsetof(type,member) );}) +#endif +#endif + +/** + * used by list + */ +struct list_head { + struct list_head *next, *prev; +}; + +/** + * list init + * @example + * 1. struct list_head your_list = LIST_HEAD_INIT(your_list); + * 2. struct list_head your_list; INIT_LIST_HEAD(&your_list); + * 3. LIST_HEAD(your_list); => struct your_list = { &(your_list), &(your_list) }; + */ + +#define LIST_HEAD_INIT(name) { &(name), &(name) } +static inline void INIT_LIST_HEAD(struct list_head *list) { + list->next = list; + list->prev = list; +} +#define LIST_HEAD(name) \ + struct list_head name = LIST_HEAD_INIT(name) + +/** + * list add + */ + +static inline void __list_add(struct list_head *newl, + struct list_head *prev, + struct list_head *next) { + next->prev = newl; + newl->next = next; + newl->prev = prev; + prev->next = newl; +} + +static inline void list_add(struct list_head *newl, struct list_head *head) { + __list_add(newl, head, head->next); +} + +static inline void list_add_tail(struct list_head *newl, struct list_head *head) { + __list_add(newl, head->prev, head); +} + +/** + * list delete + */ + +static inline void __list_del(struct list_head * prev, struct list_head * next) { + next->prev = prev; + prev->next = next; +} + +static inline void list_del(struct list_head *entry) { + __list_del(entry->prev, entry->next); + entry->next = NULL; + entry->prev = NULL; +} + +/** + * list_is_first -- tests whether @list is the first entry in list @head + * @list: the entry to test + * @head: the head of the list + */ +static inline int list_is_first(const struct list_head *list, const struct list_head *head) { + return list->prev == head; +} + +/** + * list_is_last - tests whether @list is the last entry in list @head + * @list: the entry to test + * @head: the head of the list + */ +static inline int list_is_last(const struct list_head *list, const struct list_head *head) { + return list->next == head; +} + +/** + * list_is_head - tests whether @list is the list @head + * @list: the entry to test + * @head: the head of the list + */ +static inline int list_is_head(const struct list_head *list, const struct list_head *head) { + return list == head; +} + +/** + * list_empty - tests whether a list is empty + * @head: the list to test. + */ +static inline int list_empty(const struct list_head *head) { + return head->next == head; +} + +/** + * list_for_each - iterate over a list + * @pos: the &struct list_head to use as a loop cursor. + * @head: the head for your list. + */ +#define list_for_each(pos, head) \ + for (pos = (head)->next; !list_is_head(pos, (head)); pos = pos->next) + +/** + * list_for_each_prev - iterate over a list backwards + * @pos: the &struct list_head to use as a loop cursor. + * @head: the head for your list. + */ +#define list_for_each_prev(pos, head) \ + for (pos = (head)->prev; !list_is_head(pos, (head)); pos = pos->prev) + +/** + * list sort + * by linux kernel 6.3.1 /lib/list_sort.c + * it remain use sigle linked list to merge sort + * @link https://www.geeksforgeeks.org/merge-sort-for-linked-list/ + */ + +#ifdef HAVE_KLIST_SORT +typedef int (*list_cmp_func_t)(void *, + const struct list_head *, const struct list_head *); +static void list_sort(void *priv, struct list_head *head, list_cmp_func_t cmp); +#endif + +#if defined(__NULL_KLIST_DEFINED__) && !defined(__NULL_KLIST_DEFINED_NOMOVE__) +#undef NULL +#endif + +#endif \ No newline at end of file diff --git a/libcore/vector-gdb.py b/lib/utils/ds/vector-gdb.py similarity index 98% rename from libcore/vector-gdb.py rename to lib/utils/ds/vector-gdb.py index 65d5621..d370750 100644 --- a/libcore/vector-gdb.py +++ b/lib/utils/ds/vector-gdb.py @@ -89,8 +89,8 @@ # register_printers() # vector_gdb.py -import gdb -from gdb.printing import PrettyPrinter +import gdb # type: ignore +from gdb.printing import PrettyPrinter # type: ignore class VectorPrinter: """兼容新旧注册方式的最终方案""" diff --git a/libcore/vector.h b/lib/utils/ds/vector.h similarity index 71% rename from libcore/vector.h rename to lib/utils/ds/vector.h index bce0348..d940bfb 100644 --- a/libcore/vector.h +++ b/lib/utils/ds/vector.h @@ -1,15 +1,13 @@ // vector.h -#ifndef VECTOR_H -#define VECTOR_H +#ifndef __SMCC_DS_VECTOR_H__ +#define __SMCC_DS_VECTOR_H__ -#include -#include -#include +#include #define vector_header(name, type) \ struct { \ - size_t size; \ - size_t cap; \ + rt_size_t size; \ + rt_size_t cap; \ type *data; \ } name \ @@ -24,10 +22,9 @@ do { \ if (vec.size >= vec.cap) { \ int cap = vec.cap ? vec.cap * 2 : 8; \ - void* data = realloc(vec.data, cap * sizeof(*vec.data)); \ + void* data = salloc_realloc(vec.data, cap * sizeof(*vec.data)); \ if (!data) { \ - fprintf(stderr, "vector_push: realloc failed\n"); \ - exit(1); \ + LOG_FATAL("vector_push: rt_realloc failed\n"); \ } \ (vec).cap = cap; \ (vec).data = data; \ @@ -46,7 +43,7 @@ #define vector_free(vec) \ do { \ - free((vec).data); \ + salloc_free((vec).data); \ (vec).data = NULL; \ (vec).size = (vec).cap = 0; \ } while(0) diff --git a/lib/utils/gdb.py b/lib/utils/gdb.py new file mode 100644 index 0000000..e69de29 diff --git a/lib/utils/strpool/strpool.c b/lib/utils/strpool/strpool.c new file mode 100644 index 0000000..e69de29 diff --git a/lib/utils/strpool/strpool.h b/lib/utils/strpool/strpool.h new file mode 100644 index 0000000..f0bf4cb --- /dev/null +++ b/lib/utils/strpool/strpool.h @@ -0,0 +1,12 @@ +#ifndef __SMCC_STRPOOL_H__ +#define __SMCC_STRPOOL_H__ + +#include +#include "../ds/hash.h" +typedef struct strpool { + long_alloc_t *long_alloc; +} strpool_t; + +void new_strpool(); + +#endif // __SMCC_STRPOOL_H__ diff --git a/lib/utils/symtab/symtab.c b/lib/utils/symtab/symtab.c new file mode 100644 index 0000000..e69de29 diff --git a/lib/utils/symtab/symtab.h b/lib/utils/symtab/symtab.h new file mode 100644 index 0000000..e69de29 diff --git a/lib/utils/tokbuf/token.c b/lib/utils/tokbuf/token.c new file mode 100644 index 0000000..66fc37e --- /dev/null +++ b/lib/utils/tokbuf/token.c @@ -0,0 +1,19 @@ +// #include +// #include "token.h" + +// #define ROUND_IDX(idx) ((idx) % tokbuf->cap) +// #define POW2(x) (1 << (x)) + +// void init_toks(tok_stream_t* tokbuf, int cap, +// tok_stream_close_func close, tok_stream_get_func gettok, void* stream) +// { +// tokbuf->cap_mask = POW2(cap) - 1; +// // tokbuf->buf = + +// } +// int toks_next( tok_stream_t* toks, tok_t* out); +// int toks_peek( tok_stream_t* toks, tok_t* out, int lookahead); +// const tok_t* toks_peek_ref(tok_stream_t* toks, int lookahead); +// int toks_reset(tok_stream_t* toks); +// int toks_seek( tok_stream_t* toks, int pos); +// int toks_close(tok_stream_t* toks); diff --git a/lib/utils/tokbuf/token.h b/lib/utils/tokbuf/token.h new file mode 100644 index 0000000..e250850 --- /dev/null +++ b/lib/utils/tokbuf/token.h @@ -0,0 +1,68 @@ +#ifndef __SMCC_TOKBUF_H__ +#define __SMCC_TOKBUF_H__ + +#include + +typedef struct loc { + const char *fname; + int line; + int col; + short len; +} loc_t; + +typedef enum tok_type { + TK_BASIC_INVALID, // 错误占位 + TK_BASIC_KEYWORD, // 关键字 + TK_BASIC_OPERATOR, // 操作符 + TK_BASIC_IDENTIFIER, // 标识符 + TK_BASIC_LITERAL, // 字面量 + TK_BASIC_PUNCTUATOR, // 标点符号 + TK_BASIC_EOF // 结束标记 +} tok_type_t; + +typedef union ctype { + u8_t u8; + u16_t u16; + u32_t u32; + u64_t u64; + i8_t i8; + i16_t i16; + i32_t i32; + i64_t i64; + f32_t f32; + f64_t f64; + iptr_t iptr; + uptr_t uptr; + void* ptr; +} ctype_t; + +typedef struct tok { + tok_type_t type; + int sub_type; + loc_t loc; + ctype_t val; +} tok_t; + +// typedef void(*tok_stream_close_func)(void* stream); +// typedef void(*tok_stream_get_func)(void* stream, tok_t* token); +// typedef struct tok_stream { +// int cur; +// int end; +// int cap_mask; +// tok_t* buf; + +// void* stream; +// tok_stream_close_func close; +// tok_stream_get_func gettok; +// } tok_stream_t; + +// void init_toks(tok_stream_t* tokbuf, int cap, +// tok_stream_close_func close, tok_stream_get_func gettok, void* stream); +// int toks_next( tok_stream_t* toks, tok_t* out); +// int toks_peek( tok_stream_t* toks, tok_t* out, int lookahead); +// const tok_t* toks_peek_unsafe(tok_stream_t* toks, int lookahead); +// int toks_reset(tok_stream_t* toks); +// int toks_seek( tok_stream_t* toks, int pos); +// int toks_close(tok_stream_t* toks); + +#endif // __SMCC_TOKEN_H__ diff --git a/libcore/libcore.h b/libcore/libcore.h deleted file mode 100644 index 6650943..0000000 --- a/libcore/libcore.h +++ /dev/null @@ -1,10 +0,0 @@ -#ifndef __STDCORE_H__ -#define __STDCORE_H__ - -#ifndef __NO_LINK_STDLIB -#include -#else -#error "__NO_LINK_STDLIB" -#endif - -#endif