refactor: 重构前端代码并添加日志功能
- 重命名和重构了多个文件,包括 lexer、parser 和 AST 相关代码 - 添加了日志功能,使用 LOG_* 宏替代原有的 error 和 warn 函数 - 优化了错误处理和内存分配方式 - 调整了代码结构,提高了模块化和可读性
This commit is contained in:
parent
172d72b0a0
commit
05c637e594
@ -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
|
||||
|
@ -1,16 +1,18 @@
|
||||
#define RISCV_VM_BUILDIN_ECALL
|
||||
#include "rv32gen.h"
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
#include <assert.h>
|
||||
|
||||
// 指令编码联合体(自动处理小端序)
|
||||
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[] = {
|
8
ccompiler/backend/riscv32/rv_vm/Makefile
Normal file
8
ccompiler/backend/riscv32/rv_vm/Makefile
Normal file
@ -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
|
@ -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);
|
@ -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
|
@ -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 \
|
||||
|
@ -1,8 +1,10 @@
|
||||
#include "lexer/lexer.h"
|
||||
#include "parser/symtab/symtab.h"
|
||||
#include <lib/core.h>
|
||||
#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);
|
||||
|
||||
|
@ -1,27 +1,9 @@
|
||||
#ifndef __FRONTEND_H__
|
||||
#define __FRONTEND_H__
|
||||
#ifndef __SMCC_FRONTEND_H__
|
||||
#define __SMCC_FRONTEND_H__
|
||||
|
||||
#ifndef error
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <assert.h>
|
||||
#define STD_LIBRARY
|
||||
#define error(...) do { fprintf(stderr, __VA_ARGS__); assert(0); } while (0)
|
||||
#endif
|
||||
#ifndef warn
|
||||
#include <stdio.h>
|
||||
#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
|
||||
#endif
|
||||
|
@ -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 <lib/core.h>
|
||||
#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);
|
||||
}
|
||||
|
||||
|
@ -1,6 +1,7 @@
|
||||
#ifndef __LEXER_H__
|
||||
#define __LEXER_H__
|
||||
#ifndef __SMCC_LEXER_H__
|
||||
#define __SMCC_LEXER_H__
|
||||
|
||||
#include <lib/core.h>
|
||||
#include "token.h"
|
||||
#ifndef LEXER_MAX_TOKEN_SIZE
|
||||
#define LEXER_MAX_TOKEN_SIZE 63
|
||||
|
13
ccompiler/frontend/lexer/lexer_log.h
Normal file
13
ccompiler/frontend/lexer/lexer_log.h
Normal file
@ -0,0 +1,13 @@
|
||||
#ifndef __SMCC_LEXER_LOG_H__
|
||||
#define __SMCC_LEXER_LOG_H__
|
||||
|
||||
#include <lib/rt/rt.h>
|
||||
|
||||
#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__
|
@ -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
|
||||
|
@ -1,5 +1,6 @@
|
||||
#include "../lexer.h"
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
// 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));
|
||||
}
|
||||
}
|
||||
|
@ -1,12 +1,12 @@
|
||||
#define FRONTEND_IMPLEMENTATION
|
||||
#include "../frontend.h"
|
||||
#include <lib/core.h>
|
||||
#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);
|
||||
}
|
||||
|
@ -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
|
||||
#endif
|
||||
|
@ -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) {
|
@ -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 <lib/utils/ds/vector.h>
|
||||
#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
|
@ -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();
|
||||
|
@ -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;
|
||||
|
@ -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;
|
||||
}
|
||||
}
|
||||
|
@ -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();
|
||||
|
@ -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;
|
||||
|
@ -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;
|
||||
|
@ -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();
|
||||
|
@ -1,13 +1,16 @@
|
||||
#include <lib/core.h>
|
||||
#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;
|
||||
}
|
||||
|
@ -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;
|
||||
|
@ -1,5 +1,6 @@
|
||||
// symtab.c
|
||||
#include "../../frontend.h"
|
||||
#include <lib/core.h>
|
||||
#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;
|
||||
}
|
||||
|
@ -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
|
||||
.PHONY: all clean
|
||||
|
@ -2,9 +2,7 @@
|
||||
#ifndef IR_CORE_H
|
||||
#define IR_CORE_H
|
||||
|
||||
#include "../../libcore/vector.h"
|
||||
#include <stddef.h>
|
||||
#include <stdint.h>
|
||||
#include <lib/utils/ds/vector.h>
|
||||
|
||||
// 错误码定义
|
||||
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
|
@ -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;
|
||||
}
|
||||
}
|
7
ccompiler/middleend/ir/ir_ast.h
Normal file
7
ccompiler/middleend/ir/ir_ast.h
Normal file
@ -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 //
|
76
ccompiler/middleend/ir/ir_dump.c
Normal file
76
ccompiler/middleend/ir/ir_dump.c
Normal file
@ -0,0 +1,76 @@
|
||||
#include "ir.h"
|
||||
#include "ir_lib.h"
|
||||
#include "ir_type.h"
|
||||
#include <stdio.h>
|
||||
#include <assert.h>
|
||||
|
||||
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) {
|
||||
|
||||
}
|
@ -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() {
|
||||
|
||||
}
|
0
ccompiler/middleend/middleend.c
Normal file
0
ccompiler/middleend/middleend.c
Normal file
7
ccompiler/middleend/middleend.h
Normal file
7
ccompiler/middleend/middleend.h
Normal file
@ -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__
|
35
lib/Makefile
Normal file
35
lib/Makefile
Normal file
@ -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
|
10
lib/core.c
Normal file
10
lib/core.c
Normal file
@ -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);
|
||||
}
|
9
lib/core.h
Normal file
9
lib/core.h
Normal file
@ -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__
|
33
lib/rt/log/color.h
Normal file
33
lib/rt/log/color.h
Normal file
@ -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
|
65
lib/rt/log/log.c
Normal file
65
lib/rt/log/log.c
Normal file
@ -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;
|
||||
}
|
75
lib/rt/log/log.h
Normal file
75
lib/rt/log/log.h
Normal file
@ -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
|
10
lib/rt/rt.c
Normal file
10
lib/rt/rt.c
Normal file
@ -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;
|
||||
}
|
18
lib/rt/rt.h
Normal file
18
lib/rt/rt.h
Normal file
@ -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__
|
135
lib/rt/rt_alloc.c
Normal file
135
lib/rt/rt_alloc.c
Normal file
@ -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;
|
||||
}
|
||||
}
|
36
lib/rt/rt_alloc.h
Normal file
36
lib/rt/rt_alloc.h
Normal file
@ -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
|
49
lib/rt/rt_string.c
Normal file
49
lib/rt/rt_string.c
Normal file
@ -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;
|
||||
}
|
15
lib/rt/rt_string.h
Normal file
15
lib/rt/rt_string.h
Normal file
@ -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__
|
64
lib/rt/std/rt_api_def.h
Normal file
64
lib/rt/std/rt_api_def.h
Normal file
@ -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
|
32
lib/rt/std/rt_std.c
Normal file
32
lib/rt/std/rt_std.c
Normal file
@ -0,0 +1,32 @@
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <stdint.h>
|
||||
#include <string.h>
|
||||
|
||||
#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;
|
||||
}
|
6
lib/rt/std/rt_std.h
Normal file
6
lib/rt/std/rt_std.h
Normal file
@ -0,0 +1,6 @@
|
||||
#ifndef __SMCC_RT_STD_H__
|
||||
#define __SMCC_RT_STD_H__
|
||||
|
||||
void init_rt_std();
|
||||
|
||||
#endif
|
28
lib/rt/std/rt_type.h
Normal file
28
lib/rt/std/rt_type.h
Normal file
@ -0,0 +1,28 @@
|
||||
#ifndef __SMCC_RT_TYPE_H__
|
||||
#define __SMCC_RT_TYPE_H__
|
||||
|
||||
#include <stdint.h>
|
||||
|
||||
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
|
0
lib/test/test.py
Normal file
0
lib/test/test.py
Normal file
0
lib/test/test_alloc..c
Normal file
0
lib/test/test_alloc..c
Normal file
15
lib/test/test_log.c
Normal file
15
lib/test/test_log.c
Normal file
@ -0,0 +1,15 @@
|
||||
#include <lib/core.h>
|
||||
|
||||
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");
|
||||
}
|
142
lib/utils/ds/hashtable.c
Normal file
142
lib/utils/ds/hashtable.c
Normal file
@ -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;
|
||||
}
|
27
lib/utils/ds/hashtable.h
Normal file
27
lib/utils/ds/hashtable.h
Normal file
@ -0,0 +1,27 @@
|
||||
#ifndef __SMCC_HASHTABLE_H__
|
||||
#define __SMCC_HASHTABLE_H__
|
||||
|
||||
#include <lib/rt/rt.h>
|
||||
|
||||
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__
|
158
lib/utils/ds/kllist.h
Normal file
158
lib/utils/ds/kllist.h
Normal file
@ -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
|
@ -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:
|
||||
"""兼容新旧注册方式的最终方案"""
|
@ -1,15 +1,13 @@
|
||||
// vector.h
|
||||
#ifndef VECTOR_H
|
||||
#define VECTOR_H
|
||||
#ifndef __SMCC_DS_VECTOR_H__
|
||||
#define __SMCC_DS_VECTOR_H__
|
||||
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <stdint.h>
|
||||
#include <lib/rt/rt.h>
|
||||
|
||||
#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)
|
0
lib/utils/gdb.py
Normal file
0
lib/utils/gdb.py
Normal file
0
lib/utils/strpool/strpool.c
Normal file
0
lib/utils/strpool/strpool.c
Normal file
12
lib/utils/strpool/strpool.h
Normal file
12
lib/utils/strpool/strpool.h
Normal file
@ -0,0 +1,12 @@
|
||||
#ifndef __SMCC_STRPOOL_H__
|
||||
#define __SMCC_STRPOOL_H__
|
||||
|
||||
#include <lib/core.h>
|
||||
#include "../ds/hash.h"
|
||||
typedef struct strpool {
|
||||
long_alloc_t *long_alloc;
|
||||
} strpool_t;
|
||||
|
||||
void new_strpool();
|
||||
|
||||
#endif // __SMCC_STRPOOL_H__
|
0
lib/utils/symtab/symtab.c
Normal file
0
lib/utils/symtab/symtab.c
Normal file
0
lib/utils/symtab/symtab.h
Normal file
0
lib/utils/symtab/symtab.h
Normal file
19
lib/utils/tokbuf/token.c
Normal file
19
lib/utils/tokbuf/token.c
Normal file
@ -0,0 +1,19 @@
|
||||
// #include <lib/rt/rt.h>
|
||||
// #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);
|
68
lib/utils/tokbuf/token.h
Normal file
68
lib/utils/tokbuf/token.h
Normal file
@ -0,0 +1,68 @@
|
||||
#ifndef __SMCC_TOKBUF_H__
|
||||
#define __SMCC_TOKBUF_H__
|
||||
|
||||
#include <lib/rt/rt.h>
|
||||
|
||||
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__
|
@ -1,10 +0,0 @@
|
||||
#ifndef __STDCORE_H__
|
||||
#define __STDCORE_H__
|
||||
|
||||
#ifndef __NO_LINK_STDLIB
|
||||
#include <stdlib.h>
|
||||
#else
|
||||
#error "__NO_LINK_STDLIB"
|
||||
#endif
|
||||
|
||||
#endif
|
Loading…
x
Reference in New Issue
Block a user