chore: 更新 .gitignore 文件

- 添加 docs 文件夹到忽略列表,以忽略 Doxygen 生成的文件
- 保持原有的忽略规则不变
This commit is contained in:
ZZY
2025-04-05 23:11:39 +08:00
parent c800b48ca2
commit 8d97fe896c
32 changed files with 3939 additions and 187 deletions

3
.gitignore vendored
View File

@ -1,6 +1,9 @@
.* .*
!.gitignore !.gitignore
# doxygen generated files
docs
# smcc compiler generated files # smcc compiler generated files
*.bin *.bin
.s .s

2970
Doxyfile Normal file

File diff suppressed because it is too large Load Diff

14
Makefile Normal file
View File

@ -0,0 +1,14 @@
build-docs:
doxygen Doxyfile
docs: build-docs
python -m http.server -d docs/html
smcc-build:
make -C src
smcc-clean:
make -C src clean
smcc-test: smcc-build
make -C tests/simple

View File

@ -1,9 +1,28 @@
/**
* @file core.h
* @brief 核心库初始化接口
*
* 定义SMCC库的核心初始化函数和基础服务配置
*/
#ifndef __SMCC_LIB_CORE_H__ #ifndef __SMCC_LIB_CORE_H__
#define __SMCC_LIB_CORE_H__ #define __SMCC_LIB_CORE_H__
#include "rt/rt.h" #include "rt/rt.h"
// You MUST BE call this by the start /**
* @brief 初始化核心库组件
*
* 此函数必须在调用任何其他库函数之前调用,可能负责:
* - TODO 初始化内存管理系统
* - TODO 注册基础信号处理器
* - TODO 配置默认日志系统
* - 设置运行时环境
*
* @note 必须作为程序启动后第一个调用的库函数
* @warning 重复调用不会导致未定义行为,你必须为此至少调用一次否则会导致未定义行为
* @see rt.h 中相关的运行时环境配置
*/
void init_lib_core(); void init_lib_core();
#endif // __SMCC_LIB_CORE_H__ #endif // __SMCC_LIB_CORE_H__

View File

@ -1,33 +1,59 @@
/**
* @file color.h
* @brief ANSI终端颜色控制码定义
*
* 提供跨平台的终端文本颜色和样式控制支持
*/
#ifndef __SMCC_TERMINAL_COLOR_H__ #ifndef __SMCC_TERMINAL_COLOR_H__
#define __SMCC_TERMINAL_COLOR_H__ #define __SMCC_TERMINAL_COLOR_H__
#define ANSI_FG_BLACK "\33[30m" /// @name 前景色控制码
#define ANSI_FG_RED "\33[31m" /// @{
#define ANSI_FG_GREEN "\33[32m" #define ANSI_FG_BLACK "\33[30m" ///< 黑色前景
#define ANSI_FG_YELLOW "\33[33m" #define ANSI_FG_RED "\33[31m" ///< 红色前景
#define ANSI_FG_BLUE "\33[34m" #define ANSI_FG_GREEN "\33[32m" ///< 绿色前景
#define ANSI_FG_MAGENTA "\33[35m" #define ANSI_FG_YELLOW "\33[33m" ///< 黄色前景
#define ANSI_FG_CYAN "\33[36m" #define ANSI_FG_BLUE "\33[34m" ///< 蓝色前景
#define ANSI_FG_WHITE "\33[37m" #define ANSI_FG_MAGENTA "\33[35m" ///< 品红色前景
#define ANSI_FG_CYAN "\33[36m" ///< 青色前景
#define ANSI_FG_WHITE "\33[37m" ///< 白色前景
/// @}
#define ANSI_BG_BLACK "\33[40m" /// @name 背景色控制码
#define ANSI_BG_RED "\33[41m" /// @{
#define ANSI_BG_GREEN "\33[42m" #define ANSI_BG_BLACK "\33[40m" ///< 黑色背景
#define ANSI_BG_YELLOW "\33[43m" #define ANSI_BG_RED "\33[41m" ///< 红色背景
#define ANSI_BG_BLUE "\33[44m" #define ANSI_BG_GREEN "\33[42m" ///< 绿色背景
#define ANSI_BG_MAGENTA "\33[35m" #define ANSI_BG_YELLOW "\33[43m" ///< 黄色背景
#define ANSI_BG_CYAN "\33[46m" #define ANSI_BG_BLUE "\33[44m" ///< 蓝色背景
#define ANSI_BG_WHITE "\33[47m" #define ANSI_BG_MAGENTA "\33[45m" ///< 品红色背景原始代码此处应为45m
#define ANSI_BG_CYAN "\33[46m" ///< 青色背景
#define ANSI_BG_WHITE "\33[47m" ///< 白色背景
/// @}
#define ANSI_UNDERLINED "\33[4m" /// @name 文字样式控制码
#define ANSI_BOLD "\33[1m" /// @{
#define ANSI_NONE "\33[0m" #define ANSI_UNDERLINED "\33[4m" ///< 下划线样式
#define ANSI_BOLD "\33[1m" ///< 粗体样式
#define ANSI_NONE "\33[0m" ///< 重置所有样式
/// @}
// Maybe Some Terminal Doesn't Support Color /**
* @def ANSI_FMT
* @brief 安全文本格式化宏
* @param str 目标字符串
* @param fmt ANSI格式序列可组合多个样式
*
* @note 当定义ANSI_FMT_DISABLE时自动禁用颜色输出
* @code
* printf(ANSI_FMT("Warning!", ANSI_FG_YELLOW ANSI_BOLD));
* @endcode
*/
#ifndef ANSI_FMT_DISABLE #ifndef ANSI_FMT_DISABLE
#define ANSI_FMT(str, fmt) fmt str ANSI_NONE #define ANSI_FMT(str, fmt) fmt str ANSI_NONE ///< 启用样式包裹
#else #else
#define ANSI_FMT(str, fmt) str #define ANSI_FMT(str, fmt) str ///< 禁用样式输出
#endif #endif
#endif #endif // __SMCC_TERMINAL_COLOR_H__

View File

@ -20,7 +20,8 @@ static void default_handler(log_level_t level, const char* module, const char* f
case LOG_LEVEL_TRACE: level_str = "TRACE"; break; case LOG_LEVEL_TRACE: level_str = "TRACE"; break;
default: level_str = "NOTSET"; break; default: level_str = "NOTSET"; break;
} }
/// @note: 定义 __LOG_NO_COLOR__ 会取消颜色输出
#ifndef __LOG_NO_COLOR__ #ifndef __LOG_NO_COLOR__
const char* color_code = ANSI_NONE; const char* color_code = ANSI_NONE;
switch (level) { switch (level) {
@ -50,6 +51,12 @@ static logger_t root_logger = {
.handler = default_handler, .handler = default_handler,
}; };
void init_logger(logger_t* logger, const char* name) {
logger->name = name;
logger->handler = default_handler;
log_set_level(logger, LOG_LEVEL_ALL);
}
logger_t* log_get(const char* name) { logger_t* log_get(const char* name) {
return &root_logger; return &root_logger;
} }

View File

@ -1,21 +1,39 @@
/**
* @file log.h
* @brief 日志系统核心模块(支持多级日志、断言和异常处理)
*/
#ifndef __SMCC_LOG_H__ #ifndef __SMCC_LOG_H__
#define __SMCC_LOG_H__ #define __SMCC_LOG_H__
#include "../std/rt_api_def.h" #include "../std/rt_api_def.h"
#include "color.h" #include "color.h"
/**
* @brief 日志级别枚举
*
* 定义日志系统的输出级别和组合标志位
*/
typedef enum log_level { typedef enum log_level {
LOG_LEVEL_NOTSET = 0, LOG_LEVEL_NOTSET = 0, ///< 未设置级别(继承默认配置)
LOG_LEVEL_DEBUG = 1 << 0, LOG_LEVEL_DEBUG = 1 << 0, ///< 调试信息(开发阶段详细信息)
LOG_LEVEL_INFO = 1 << 1, LOG_LEVEL_INFO = 1 << 1, ///< 常规信息(系统运行状态)
LOG_LEVEL_WARN = 1 << 2, LOG_LEVEL_WARN = 1 << 2, ///< 警告信息(潜在问题提示)
LOG_LEVEL_ERROR = 1 << 3, LOG_LEVEL_ERROR = 1 << 3, ///< 错误信息(可恢复的错误)
LOG_LEVEL_FATAL = 1 << 4, LOG_LEVEL_FATAL = 1 << 4, ///< 致命错误(导致程序终止的严重错误)
LOG_LEVEL_TRACE = 1 << 5, ///< 追踪(性能追踪或者栈帧追踪)
LOG_LEVEL_TRACE = 1 << 5, LOG_LEVEL_ALL = 0xFF, ///< 全级别标志(组合所有日志级别)
LOG_LEVEL_ALL = 0xFF,
} log_level_t; } log_level_t;
/**
* @brief 日志处理回调函数类型
* @param level 日志级别
* @param module 模块名称可为NULL
* @param file 源文件名
* @param line 代码行号
* @param message 格式化后的日志消息
* @todo 待实现模块名称,输入的模块名称,都将被忽略
*/
typedef void (*log_handler)( typedef void (*log_handler)(
log_level_t level, log_level_t level,
const char* module, const char* module,
@ -25,51 +43,119 @@ typedef void (*log_handler)(
); );
#ifndef LOGGER_MAX_BUF_SIZE #ifndef LOGGER_MAX_BUF_SIZE
#define LOGGER_MAX_BUF_SIZE 256 #define LOGGER_MAX_BUF_SIZE 512 ///< 单条日志最大缓冲区尺寸
#endif #endif
/**
* @brief 日志器实例结构体
*
* 每个日志器实例维护独立的配置和缓冲区
*/
typedef struct logger { typedef struct logger {
const char* name; const char* name; ///< 日志器名称(用于模块区分)
log_level_t level; log_level_t level; ///< 当前设置的日志级别
log_handler handler; log_handler handler; ///< 日志处理回调函数
char buf[LOGGER_MAX_BUF_SIZE]; char buf[LOGGER_MAX_BUF_SIZE]; ///< 格式化缓冲区
} logger_t; } logger_t;
/**
* @brief 初始化日志实例 其余参数设置为默认值
* @param[in] logger 日志器实例指针
* @param[in] name 日志器名称NULL表示获取默认日志器名称
*/
void init_logger(logger_t* logger, const char* name);
// TODO log_set(); 暂未实现 日志注册
/**
* @brief 获取或创建日志器实例
* @param[in] name 日志器名称NULL表示获取默认日志器
* @return 日志器实例指针
* @warning 若没有找到相应日志器则会返回根日志器
*/
logger_t* log_get(const char* name); logger_t* log_get(const char* name);
/**
* @brief 设置日志级别
* @param[in] logger 目标日志器实例
* @param[in] level 要设置的日志级别(可组合多个级别)
*/
void log_set_level(logger_t* logger, log_level_t level); void log_set_level(logger_t* logger, log_level_t level);
/**
* @brief 设置自定义日志处理器
* @param[in] logger 目标日志器实例
* @param[in] handler 自定义处理函数NULL恢复默认处理
*/
void log_set_handler(logger_t* logger, log_handler handler); void log_set_handler(logger_t* logger, log_handler handler);
#ifndef LOG_MAX_MAROC_BUF_SIZE #ifndef LOG_MAX_MAROC_BUF_SIZE
#define LOG_MAX_MAROC_BUF_SIZE LOGGER_MAX_BUF_SIZE #define LOG_MAX_MAROC_BUF_SIZE LOGGER_MAX_BUF_SIZE ///< 宏展开缓冲区尺寸
#endif #endif
#define _LOG(_level_, _msg_, ...) \
/**
* @def _LOG
* @brief 内部日志宏(供其他日志宏调用)
* @param _module_ 模块实例NULL表示使用默认日志器
* @param _level_ 日志级别
* @param _msg_ 格式字符串
* @param ... 可变参数列表
*/
#define _LOG(_module_, _level_, _msg_, ...) \
do { \ do { \
logger_t* _logger = log_get(NULL); \ logger_t* _logger; \
if (!_module_) { \
_logger = log_get(NULL); \
} \
else _logger = _module_; \
if (_logger && _logger->handler && (_logger->level & (_level_))) { \ if (_logger && _logger->handler && (_logger->level & (_level_))) { \
rt.snprintf(_logger->buf, sizeof(_logger->buf), (_msg_), ##__VA_ARGS__); \ rt.snprintf(_logger->buf, sizeof(_logger->buf), (_msg_), ##__VA_ARGS__); \
_logger->handler((_level_), _logger->name, __FILE__, __LINE__, _logger->buf); \ _logger->handler((_level_), _logger->name, __FILE__, __LINE__, _logger->buf); \
} \ } \
} while(0) } while(0)
#define LOG_NOTSET(...) _LOG(LOG_LEVEL_NOTSET, __VA_ARGS__) /// @name 模块日志宏
#define LOG_DEBUG(...) _LOG(LOG_LEVEL_DEBUG, __VA_ARGS__) /// @{
#define LOG_INFO(...) _LOG(LOG_LEVEL_INFO, __VA_ARGS__) #define MLOG_NOTSET(module, ...) _LOG(module, LOG_LEVEL_NOTSET, __VA_ARGS__) ///< 未分类日志
#define LOG_WARN(...) _LOG(LOG_LEVEL_WARN, __VA_ARGS__) #define MLOG_DEBUG( module, ...) _LOG(module, LOG_LEVEL_DEBUG, __VA_ARGS__) ///< 调试日志需启用DEBUG级别
#define LOG_ERROR(...) _LOG(LOG_LEVEL_ERROR, __VA_ARGS__) #define MLOG_INFO( module, ...) _LOG(module, LOG_LEVEL_INFO, __VA_ARGS__) ///< 信息日志(常规运行日志)
#define LOG_FATAL(...) _LOG(LOG_LEVEL_FATAL, __VA_ARGS__) #define MLOG_WARN( module, ...) _LOG(module, LOG_LEVEL_WARN, __VA_ARGS__) ///< 警告日志(潜在问题)
#define LOG_TRACE(...) _LOG(LOG_LEVEL_TRACE, __VA_ARGS__) #define MLOG_ERROR( module, ...) _LOG(module, LOG_LEVEL_ERROR, __VA_ARGS__) ///< 错误日志(可恢复错误)
#define MLOG_FATAL( module, ...) _LOG(module, LOG_LEVEL_FATAL, __VA_ARGS__) ///< 致命错误日志(程序终止前)
#define MLOG_TRACE( module, ...) _LOG(module, LOG_LEVEL_TRACE, __VA_ARGS__) ///< 追踪日志(调用栈跟踪)
/// @}
/// @name 快捷日志宏
/// @{
#define LOG_NOTSET(...) _LOG(NULL, LOG_LEVEL_NOTSET, __VA_ARGS__) ///< 未分类日志
#define LOG_DEBUG(...) _LOG(NULL, LOG_LEVEL_DEBUG, __VA_ARGS__) ///< 调试日志需启用DEBUG级别
#define LOG_INFO(...) _LOG(NULL, LOG_LEVEL_INFO, __VA_ARGS__) ///< 信息日志(常规运行日志)
#define LOG_WARN(...) _LOG(NULL, LOG_LEVEL_WARN, __VA_ARGS__) ///< 警告日志(潜在问题)
#define LOG_ERROR(...) _LOG(NULL, LOG_LEVEL_ERROR, __VA_ARGS__) ///< 错误日志(可恢复错误)
#define LOG_FATAL(...) _LOG(NULL, LOG_LEVEL_FATAL, __VA_ARGS__) ///< 致命错误日志(程序终止前)
#define LOG_TRACE(...) _LOG(NULL, LOG_LEVEL_TRACE, __VA_ARGS__) ///< 追踪日志(调用栈跟踪)
/// @}
/**
* @def _Assert
* @brief 断言检查内部宏
* @param cond 检查条件表达式
* @param ... 错误信息参数(格式字符串+参数)
*/
#define _Assert(cond, ...) \ #define _Assert(cond, ...) \
do { \ do { \
if (!(cond)) { \ if (!(cond)) { \
LOG_FATAL(__VA_ARGS__); \ LOG_FATAL(__VA_ARGS__); \
} \ } \
} while (0) } 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 /// @name 断言工具宏
/// @{
#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 // __SMCC_LOG_H__

View File

@ -1,36 +1,132 @@
/**
* @file rt_alloc.h
* @brief 内存分配器接口
*
* 提供三种内存分配器实现:简单分配器、固定大小分配器和长块分配器
*/
#ifndef __SMCC_RT_ALLOC_H__ #ifndef __SMCC_RT_ALLOC_H__
#define __SMCC_RT_ALLOC_H__ #define __SMCC_RT_ALLOC_H__
#include "std/rt_api_def.h" #include "std/rt_api_def.h"
// Simple or Static Allocator
/** @defgroup simple_allocator 简单分配器 */
/**
* @brief 分配指定大小的内存块
* @param size 请求分配的内存大小(字节)
* @return 成功返回内存指针失败返回NULL
*/
void* salloc_alloc(int size); void* salloc_alloc(int size);
/**
* @brief 重新分配内存块
* @param ptr 原内存指针
* @param size 新内存大小(字节)
* @return 成功返回新内存指针失败返回NULL
*/
void* salloc_realloc(void* ptr, int size); void* salloc_realloc(void* ptr, int size);
/**
* @brief 释放内存块
* @param ptr 要释放的内存指针
*/
void salloc_free(void* ptr); void salloc_free(void* ptr);
/** @defgroup fixed_allocator 固定大小分配器 */
/**
* @struct fixed_alloc_t
* @brief 固定大小内存分配器上下文
*/
typedef struct fixed_alloc { typedef struct fixed_alloc {
/** @brief 内存页链表头指针 */
void* page_list; void* page_list;
/** @brief 空闲块链表头指针 */
void* free_list; void* free_list;
/** @brief 每个内存块的固定大小 */
int block_size; int block_size;
/** @brief 每页包含的块数量 */
int blocks_per_page; int blocks_per_page;
} fixed_alloc_t; } fixed_alloc_t;
/**
* @brief 初始化固定大小分配器
* @param fa 分配器上下文指针
* @param fixed_size 每个内存块的固定大小
* @param init_size 初始预分配块数量
*/
void falloc_init(fixed_alloc_t* fa, int fixed_size, int init_size); void falloc_init(fixed_alloc_t* fa, int fixed_size, int init_size);
/**
* @brief 分配固定大小内存块
* @param fa 分配器上下文指针
* @return 成功返回内存指针失败返回NULL
*/
void* falloc_alloc(fixed_alloc_t* fa); void* falloc_alloc(fixed_alloc_t* fa);
/**
* @brief 释放内存块
* @param fa 分配器上下文指针
* @param ptr 要释放的内存指针
*/
void falloc_free(fixed_alloc_t* fa, void* ptr); void falloc_free(fixed_alloc_t* fa, void* ptr);
/**
* @brief 销毁分配器并释放所有内存页
* @param fa 分配器上下文指针
*/
void falloc_destroy(fixed_alloc_t* fa); void falloc_destroy(fixed_alloc_t* fa);
/** @defgroup long_allocator 长块分配器 */
/**
* @struct long_block_t
* @brief 长块内存块头结构
*/
typedef struct long_block { typedef struct long_block {
/** @brief 指向下一个内存块的指针 */
struct long_block* next; struct long_block* next;
/** @brief 当前块使用状态标志 */
int used; int used;
} long_block_t; } long_block_t;
/**
* @struct long_alloc_t
* @brief 长块分配器上下文
*/
typedef struct long_alloc { typedef struct long_alloc {
/** @brief 当前内存块指针 */
long_block_t* current; long_block_t* current;
/** @brief 内存块的标准大小 */
int block_size; int block_size;
} long_alloc_t; } long_alloc_t;
/**
* @brief 初始化长块分配器
* @param la 分配器上下文指针
*/
void lalloc_init(long_alloc_t* la); void lalloc_init(long_alloc_t* la);
/**
* @brief 分配指定大小的内存块
* @param la 分配器上下文指针
* @param size 请求分配的内存大小
* @return 成功返回内存指针失败返回NULL
*/
void* lalloc_alloc(long_alloc_t* la, int size); void* lalloc_alloc(long_alloc_t* la, int size);
/**
* @brief 标记释放内存块(实际在块耗尽时统一释放)
* @param la 分配器上下文指针
* @param ptr 要释放的内存指针
*/
void lalloc_free(long_alloc_t* la, void* ptr); void lalloc_free(long_alloc_t* la, void* ptr);
/**
* @brief 销毁分配器并释放所有内存块
* @param la 分配器上下文指针
*/
void lalloc_destroy(long_alloc_t* la); void lalloc_destroy(long_alloc_t* la);
#endif #endif // __SMCC_RT_ALLOC_H__

View File

@ -25,11 +25,11 @@ void* rt_memcpy(void* restrict dest, const void* restrict src, rt_size_t n) {
return dest; return dest;
} }
void* rt_memset(void* s, int c, rt_size_t n) { void* rt_memset(void* dest, int val, rt_size_t n) {
u8_t* p = s; u8_t* p = dest;
for (rt_size_t i = 0; i < n; ++i) for (rt_size_t i = 0; i < n; ++i)
p[i] = (u8_t)c; p[i] = (u8_t)val;
return s; return dest;
} }
rt_size_t rt_strlen(const char* s) { rt_size_t rt_strlen(const char* s) {

View File

@ -1,15 +1,67 @@
/**
* @file rt_string.h
* @brief 运行时字符串与内存操作
*
* 提供基本的内存操作和字符串处理函数实现
*/
#ifndef __SMCC_RT_STRING_H__ #ifndef __SMCC_RT_STRING_H__
#define __SMCC_RT_STRING_H__ #define __SMCC_RT_STRING_H__
#include "std/rt_api_def.h" #include "std/rt_api_def.h"
/** @defgroup memory_operations 内存操作 */
/**
* @brief 内存区域比较
* @param s1 第一个内存区域指针
* @param s2 第二个内存区域指针
* @param n 比较的字节数
* @return 差异值(<0: s1<s2, 0: 相等, >0: s1>s2
*/
int rt_memcmp(const void* s1, const void* s2, rt_size_t n); int rt_memcmp(const void* s1, const void* s2, rt_size_t n);
/**
* @brief 安全内存拷贝(要求内存区域不重叠)
* @param dest 目标内存地址restrict修饰
* @param src 源内存地址restrict修饰
* @param n 拷贝的字节数
* @return 目标内存地址
*/
void* rt_memcpy(void* restrict dest, const void* restrict src, rt_size_t n);
/**
* @brief 内存区域填充
* @param s 目标内存地址
* @param c 填充字节值转换为unsigned char
* @param n 填充的字节数
* @return 原始内存地址
*/
void* rt_memset(void* dest, int val, rt_size_t n);
/** @defgroup string_operations 字符串操作 */
/**
* @brief 字符串比较
* @param s1 第一个字符串指针
* @param s2 第二个字符串指针
* @return 差异值(<0: s1<s2, 0: 相等, >0: s1>s2
*/
int rt_strcmp(const char* s1, const char* s2); 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); * @brief 计算字符串长度
* @param s 字符串指针
* @return 字符串长度(不含终止符)
*/
rt_size_t rt_strlen(const char* s); rt_size_t rt_strlen(const char* s);
/**
* @brief 计算字符串哈希值
* @param s 输入字符串
* @return 32位无符号哈希值
* @note 使用FNV-1a哈希算法实现
*/
u32_t rt_strhash(const char* s); u32_t rt_strhash(const char* s);
#endif // __SMCC_RT_STRING_H__ #endif // __SMCC_RT_STRING_H__

View File

@ -1,3 +1,10 @@
/**
* @file rt_api_def.h
* @brief SMCC运行时库接口定义
*
* 定义运行时基础API函数指针类型及运行时接口结构体
*/
#ifndef __SMCC_RT_API_DEF_H__ #ifndef __SMCC_RT_API_DEF_H__
#define __SMCC_RT_API_DEF_H__ #define __SMCC_RT_API_DEF_H__
@ -5,48 +12,172 @@
#ifndef __RT_SIZE_TYPE__ #ifndef __RT_SIZE_TYPE__
#define __RT_SIZE_TYPE__ #define __RT_SIZE_TYPE__
/**
* @typedef rt_size_t
* @brief 表示内存大小的类型定义
*/
typedef usz_t rt_size_t; typedef usz_t rt_size_t;
#endif #endif
/**
* @typedef rt_malloc
* @brief 内存分配函数指针类型
* @param size 需要分配的内存大小
* @return 分配的内存指针失败返回NULL
*/
typedef void* (*rt_malloc)(rt_size_t size); typedef void* (*rt_malloc)(rt_size_t size);
/**
* @typedef rt_free
* @brief 内存释放函数指针类型
* @param ptr 需要释放的内存指针
*/
typedef void (*rt_free)(void* ptr); typedef void (*rt_free)(void* ptr);
/**
* @typedef rt_exit
* @brief 程序退出函数指针类型
* @param code 退出状态码
*/
typedef void (*rt_exit)(int code); typedef void (*rt_exit)(int code);
/** @defgroup file_io 文件I/O相关类型 */
#ifndef __RT_FILE_TYPE__ #ifndef __RT_FILE_TYPE__
#define __RT_FILE_TYPE__ #define __RT_FILE_TYPE__
/**
* @typedef rt_file_t
* @brief 文件句柄类型定义
*/
typedef void* rt_file_t; typedef void* rt_file_t;
#endif #endif
/** @brief 标准输入文件句柄 */
extern rt_file_t rt_stdin; extern rt_file_t rt_stdin;
/** @brief 标准输出文件句柄 */
extern rt_file_t rt_stdout; extern rt_file_t rt_stdout;
/** @brief 标准错误文件句柄 */
extern rt_file_t rt_stderr; extern rt_file_t rt_stderr;
/**
* @typedef rt_fopen_t
* @brief 文件打开函数指针类型
* @param file_name 文件名
* @param mode 打开模式同fopen
* @return 文件句柄失败返回NULL
*/
typedef rt_file_t (*rt_fopen_t)(const char* file_name, const char* mode); typedef rt_file_t (*rt_fopen_t)(const char* file_name, const char* mode);
typedef int (*rt_fflush_t)(rt_file_t*file);
/**
* @typedef rt_fflush_t
* @brief 文件缓冲刷新函数指针类型
* @param file 文件句柄指针
* @return 成功返回0失败返回非0值
*/
typedef int (*rt_fflush_t)(rt_file_t* file);
/**
* @typedef rt_fclose_t
* @brief 文件关闭函数指针类型
* @param file 文件句柄
* @return 成功返回0失败返回EOF
*/
typedef int (*rt_fclose_t)(rt_file_t file); typedef int (*rt_fclose_t)(rt_file_t file);
/**
* @typedef rt_fread_t
* @brief 文件读取函数指针类型
* @param dst_buf 目标缓冲区
* @param elem_size 单个元素大小
* @param count 元素数量
* @param file 文件句柄
* @return 实际读取的元素数量
*/
typedef int (*rt_fread_t)(void * dst_buf, rt_size_t elem_size, rt_size_t count, rt_file_t file); typedef int (*rt_fread_t)(void * dst_buf, rt_size_t elem_size, rt_size_t count, rt_file_t file);
/**
* @typedef rt_fwrite_t
* @brief 文件写入函数指针类型
* @param buf 源缓冲区
* @param size 单个元素大小
* @param count 元素数量
* @param file 文件句柄
* @return 实际写入的元素数量
*/
typedef int (*rt_fwrite_t)(const void * buf, rt_size_t 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);
/** @defgroup utility 实用工具函数 */
/**
* @typedef rt_fprintf_t
* @brief 格式化输出函数指针类型
* @param file 文件句柄
* @param format 格式化字符串
* @param ... 可变参数
* @return 输出的字符数
*/
typedef int (*rt_fprintf_t)(void * file, const char *format, ...); typedef int (*rt_fprintf_t)(void * file, const char *format, ...);
/**
* @typedef rt_snprintf_t
* @brief 安全格式化字符串函数指针类型
* @param stream 目标缓冲区
* @param n 缓冲区大小
* @param format 格式化字符串
* @param ... 可变参数
* @return 写入的字符数(不含终止符)
*/
typedef int (*rt_snprintf_t)(char * stream, rt_size_t n, const char * format, ...); typedef int (*rt_snprintf_t)(char * stream, rt_size_t n, const char * format, ...);
/**
* @typedef rt_realloc_t
* @brief 内存重分配函数指针类型
* @param memory 原内存指针
* @param new_size 新内存大小
* @return 新内存指针失败返回NULL
*/
typedef void* (*rt_realloc_t)(void *memory, rt_size_t new_size); typedef void* (*rt_realloc_t)(void *memory, rt_size_t new_size);
/**
* @struct smcc_rt_t
* @brief 运行时接口集合
*
* 包含内存管理、文件操作等核心运行时函数的指针集合
*/
typedef struct smcc_rt { typedef struct smcc_rt {
/** @brief 内存分配函数指针 */
rt_malloc _malloc; rt_malloc _malloc;
/** @brief 内存释放函数指针 */
rt_free _free; rt_free _free;
/** @brief 程序退出函数指针 */
rt_exit exit; rt_exit exit;
/** @brief 文件打开函数指针 */
rt_fopen_t fopen; rt_fopen_t fopen;
/** @brief 文件缓冲刷新函数指针 */
rt_fflush_t fflush; rt_fflush_t fflush;
/** @brief 文件关闭函数指针 */
rt_fclose_t fclose; rt_fclose_t fclose;
/** @brief 文件读取函数指针 */
rt_fread_t fread; rt_fread_t fread;
/** @brief 文件写入函数指针 */
rt_fwrite_t fwrite; rt_fwrite_t fwrite;
// Optional useful runtime /** @name 可选工具函数 */
///@{
/** @brief 格式化输出函数指针(可选) */
rt_fprintf_t fprintf; rt_fprintf_t fprintf;
/** @brief 安全格式化字符串函数指针(可选) */
rt_snprintf_t snprintf; rt_snprintf_t snprintf;
/** @brief 内存重分配函数指针(可选) */
rt_realloc_t _realloc; rt_realloc_t _realloc;
///@}
} smcc_rt_t; } smcc_rt_t;
/** @brief 全局运行时接口实例 */
extern const smcc_rt_t rt; extern const smcc_rt_t rt;
/** @brief 空指针定义 */
#define NULL ((void *)0) #define NULL ((void *)0)
#endif #endif // __SMCC_RT_API_DEF_H__

View File

@ -3,4 +3,4 @@
void init_rt_std(); void init_rt_std();
#endif #endif // __SMCC_RT_STD_H__

View File

@ -1,29 +1,120 @@
/**
* @file rt_type.h
* @brief 基础类型定义
*
* 定义跨平台基础数据类型别名基于C99标准头文件<stdint.h>和<stddef.h>
*/
#ifndef __SMCC_RT_TYPE_H__ #ifndef __SMCC_RT_TYPE_H__
#define __SMCC_RT_TYPE_H__ #define __SMCC_RT_TYPE_H__
#include <stddef.h> #include <stddef.h>
#include <stdint.h> #include <stdint.h>
/** @defgroup integer_types 整数类型 */
/**
* @typedef i8_t
* @brief 8位有符号整数
*/
typedef int8_t i8_t; typedef int8_t i8_t;
/**
* @typedef i16_t
* @brief 16位有符号整数
*/
typedef int16_t i16_t; typedef int16_t i16_t;
/**
* @typedef i32_t
* @brief 32位有符号整数
*/
typedef int32_t i32_t; typedef int32_t i32_t;
/**
* @typedef i64_t
* @brief 64位有符号整数
*/
typedef int64_t i64_t; typedef int64_t i64_t;
/**
* @typedef u8_t
* @brief 8位无符号整数
*/
typedef uint8_t u8_t; typedef uint8_t u8_t;
/**
* @typedef u16_t
* @brief 16位无符号整数
*/
typedef uint16_t u16_t; typedef uint16_t u16_t;
/**
* @typedef u32_t
* @brief 32位无符号整数
*/
typedef uint32_t u32_t; typedef uint32_t u32_t;
/**
* @typedef u64_t
* @brief 64位无符号整数
*/
typedef uint64_t u64_t; typedef uint64_t u64_t;
/** @defgroup floating_point 浮点类型 */
/**
* @typedef f32_t
* @brief 32位单精度浮点数
*/
typedef float f32_t; typedef float f32_t;
/**
* @typedef f64_t
* @brief 64位双精度浮点数
*/
typedef double f64_t; typedef double f64_t;
/** @defgroup pointer_types 指针类型 */
/**
* @typedef iptr_t
* @brief 带符号指针类型intptr_t别名
*/
typedef intptr_t iptr_t; typedef intptr_t iptr_t;
/**
* @typedef uptr_t
* @brief 无符号指针类型uintptr_t别名
*/
typedef uintptr_t uptr_t; typedef uintptr_t uptr_t;
/** @defgroup size_types 大小类型 */
/**
* @typedef usz_t
* @brief 无符号大小类型size_t别名
*/
typedef size_t usz_t; typedef size_t usz_t;
// /**
// * @typedef isz_t
// * @brief 带符号大小类型ssize_t别名
// */
// typedef ssize_t isz_t; // typedef ssize_t isz_t;
// /** @defgroup word_types 字类型 */
//
// /**
// * @typedef uw_t
// * @brief 无符号机器字类型32位
// */
// typedef u32_t uw_t; // typedef u32_t uw_t;
//
// /**
// * @typedef iw_t
// * @brief 带符号机器字类型32位
// */
// typedef i32_t iw_t; // typedef i32_t iw_t;
#endif #endif // __SMCC_RT_TYPE_H__

View File

@ -52,7 +52,7 @@ static void adjust_capacity(hash_table_t* ht, int new_cap) {
new_cap = next_power_of_two(new_cap); new_cap = next_power_of_two(new_cap);
Assert(new_cap >= ht->entries.cap); Assert(new_cap >= ht->entries.cap);
vector_header(old_entries, hash_entry_t); VECTOR_HEADER(old_entries, hash_entry_t);
old_entries.data = ht->entries.data; old_entries.data = ht->entries.data;
old_entries.cap = ht->entries.cap; old_entries.cap = ht->entries.cap;

View File

@ -1,3 +1,10 @@
/**
* @file hashtable.h
* @brief 开放寻址法哈希表实现
*
* 提供基于向量容器的哈希表实现,支持动态扩容和墓碑机制
*/
#ifndef __SMCC_HASHTABLE_H__ #ifndef __SMCC_HASHTABLE_H__
#define __SMCC_HASHTABLE_H__ #define __SMCC_HASHTABLE_H__
@ -5,39 +12,113 @@
#include <lib/rt/rt_alloc.h> #include <lib/rt/rt_alloc.h>
#include "vector.h" #include "vector.h"
// 哈希表条目状态标记 /**
* @enum ht_entry_state_t
* @brief 哈希表条目状态标识
*/
typedef enum hash_table_entry_state { typedef enum hash_table_entry_state {
ENTRY_EMPTY, ENTRY_EMPTY, /**< 空槽位(从未使用过) */
ENTRY_ACTIVE, ENTRY_ACTIVE, /**< 有效条目(包含键值对) */
ENTRY_TOMBSTONE ENTRY_TOMBSTONE /**< 墓碑标记(已删除条目) */
} ht_entry_state_t; } ht_entry_state_t;
// 哈希表条目结构不管理key/value内存 /**
* @struct hash_entry_t
* @brief 哈希表条目结构
*
* @note key/value内存由调用者管理哈希表不负责其生命周期
*/
typedef struct hash_entry { typedef struct hash_entry {
const void* key; // 由调用者管理 const void* key; /**< 键指针(不可变) */
void* value; // 由调用者管理 void* value; /**< 值指针 */
u32_t hash; // 预计算哈希值 u32_t hash; /**< 预计算哈希值(避免重复计算) */
ht_entry_state_t state; // 条目状态 ht_entry_state_t state; /**< 当前条目状态 */
} hash_entry_t; } hash_entry_t;
// 哈希表主体结构 /**
* @struct hash_table_t
* @brief 哈希表主体结构
*
* 使用开放寻址法实现,采用墓碑标记处理删除操作
*/
typedef struct hash_table { typedef struct hash_table {
vector_header(entries, hash_entry_t); // 使用vector管理条目 VECTOR_HEADER(entries, hash_entry_t); /**< 条目存储容器 */
u32_t count; // 有效条目数(不含墓碑) u32_t count; /**< 有效条目数(不含墓碑) */
u32_t tombstone_count; // 墓碑数量 u32_t tombstone_count; /**< 墓碑条目数量 */
/**
* @brief 哈希函数指针
* @param key 键指针
* @return 32位无符号哈希值
*/
u32_t (*hash_func)(const void* key); u32_t (*hash_func)(const void* key);
/**
* @brief 键比较函数指针
* @param key1 第一个键指针
* @param key2 第二个键指针
* @return 相同返回0不同返回非0
*/
int(*key_cmp)(const void* key1, const void* key2); int(*key_cmp)(const void* key1, const void* key2);
} hash_table_t; } hash_table_t;
// WARN you need set hash_func and key_cmp before use /**
void init_hashtable(hash_table_t* ht) ; * @brief 初始化哈希表结构
* @param ht 哈希表实例指针
*
* @warning 必须设置hash_func和key_cmp后才能使用
*/
void init_hashtable(hash_table_t* ht);
/**
* @brief 插入/更新键值对
* @param ht 哈希表实例指针
* @param key 键指针
* @param value 值指针
* @return 被替换的旧值指针无替换返回NULL
*/
void* hashtable_set(hash_table_t* ht, const void* key, void* value); void* hashtable_set(hash_table_t* ht, const void* key, void* value);
/**
* @brief 查找键对应值
* @param ht 哈希表实例指针
* @param key 查找键指针
* @return 找到返回值指针未找到返回NULL
*/
void* hashtable_get(hash_table_t* ht, const void* key); void* hashtable_get(hash_table_t* ht, const void* key);
/**
* @brief 删除键值对
* @param ht 哈希表实例指针
* @param key 要删除的键指针
* @return 被删除的值指针不存在返回NULL
*
* @note 实际采用墓碑标记方式删除
*/
void* hashtable_del(hash_table_t* ht, const void* key); void* hashtable_del(hash_table_t* ht, const void* key);
/**
* @brief 销毁哈希表
* @param ht 哈希表实例指针
*
* @note 仅释放哈希表内部内存不会释放key/value内存
*/
void hashtable_destory(hash_table_t* ht); void hashtable_destory(hash_table_t* ht);
/**
* @typedef hash_table_iter_func
* @brief 哈希表迭代回调函数类型
* @param key 当前键指针
* @param value 当前值指针
* @param context 用户上下文指针
* @return 返回非0停止迭代
*/
typedef int (*hash_table_iter_func)(const void* key, void* value, void* context); typedef int (*hash_table_iter_func)(const void* key, void* value, void* context);
/**
* @brief 遍历哈希表所有有效条目
* @param ht 哈希表实例指针
* @param iter_func 迭代回调函数
* @param context 用户上下文指针
*/
void hashtable_foreach(hash_table_t* ht, hash_table_iter_func iter_func, void* context); void hashtable_foreach(hash_table_t* ht, hash_table_iter_func iter_func, void* context);
#endif // __SMCC_HASHTABLE_H__ #endif // __SMCC_HASHTABLE_H__

View File

@ -1,17 +1,44 @@
// vector.h /**
* @file vector.h
* @brief 动态数组Vector实现
*
* 提供类型安全的动态数组容器实现,支持自动扩容和基本操作
*/
#ifndef __SMCC_DS_VECTOR_H__ #ifndef __SMCC_DS_VECTOR_H__
#define __SMCC_DS_VECTOR_H__ #define __SMCC_DS_VECTOR_H__
#include <lib/rt/rt.h> #include <lib/rt/rt.h>
#define vector_header(name, type) \ /** @defgroup vector_struct 数据结构定义 */
struct { \
rt_size_t size; \
rt_size_t cap; \
type *data; \
} name \
// You can't malloc at init function becase some user just need a header /**
* @def VECTOR_HEADER(name, type)
* @brief 声明向量结构体
* @param name 结构体变量名
* @param type 存储的数据类型
*
* 生成包含size/cap/data三个字段的结构体定义
* - size: 当前元素数量
* - cap: 数组容量
* - data: 存储数组指针
*/
#define VECTOR_HEADER(name, type) \
struct { \
rt_size_t size; /**< 当前元素数量 */ \
rt_size_t cap; /**< 数组容量 */ \
type *data; /**< 数据存储指针 */ \
} name
/** @defgroup vector_operations 向量操作宏 */
/**
* @def vector_init(vec)
* @brief 初始化向量结构体
* @param vec 要初始化的向量结构体变量
*
* @note 此宏不会分配内存,仅做零初始化
*/
#define vector_init(vec) \ #define vector_init(vec) \
do { \ do { \
(vec).size = 0, \ (vec).size = 0, \
@ -19,6 +46,15 @@
(vec).data = 0; \ (vec).data = 0; \
} while(0) } while(0)
/**
* @def vector_push(vec, value)
* @brief 添加元素到向量末尾
* @param vec 目标向量结构体
* @param value 要添加的值(需匹配存储类型)
*
* @note 当容量不足时自动扩容为2倍初始容量为8
* @warning 内存分配失败时会触发LOG_FATAL
*/
#define vector_push(vec, value) \ #define vector_push(vec, value) \
do { \ do { \
if (vec.size >= vec.cap) { \ if (vec.size >= vec.cap) { \
@ -33,15 +69,43 @@
(vec).data[(vec).size++] = value; \ (vec).data[(vec).size++] = value; \
} while(0) } while(0)
/**
* @def vector_pop(vec)
* @brief 弹出最后一个元素
* @param vec 目标向量结构体
* @return 最后元素的引用
* @warning 需确保size > 0时使用
*/
#define vector_pop(vec) \ #define vector_pop(vec) \
((vec).data[--(vec).size]) ((vec).data[--(vec).size])
/**
* @def vector_at(vec, idx)
* @brief 获取指定索引元素
* @param vec 目标向量结构体
* @param idx 元素索引0 <= idx < size
* @return 对应元素的引用
*/
#define vector_at(vec, idx) \ #define vector_at(vec, idx) \
(((vec).data)[idx]) (((vec).data)[idx])
/**
* @def vector_idx(vec, ptr)
* @brief 获取元素指针对应的索引
* @param vec 目标向量结构体
* @param ptr 元素指针需在data数组范围内
* @return 元素索引值
*/
#define vector_idx(vec, ptr) \ #define vector_idx(vec, ptr) \
((ptr) - (vec).data) ((ptr) - (vec).data)
/**
* @def vector_free(vec)
* @brief 释放向量内存
* @param vec 目标向量结构体
*
* @note 释放后需重新初始化才能再次使用
*/
#define vector_free(vec) \ #define vector_free(vec) \
do { \ do { \
salloc_free((vec).data); \ salloc_free((vec).data); \
@ -49,4 +113,4 @@
(vec).size = (vec).cap = 0; \ (vec).size = (vec).cap = 0; \
} while(0) } while(0)
#endif #endif // __SMCC_DS_VECTOR_H__

View File

@ -1,3 +1,10 @@
/**
* @file strpool.h
* @brief 字符串池实现
*
* 提供字符串驻留String Interning功能保证相同字符串的唯一性存储
*/
#ifndef __SMCC_STRPOOL_H__ #ifndef __SMCC_STRPOOL_H__
#define __SMCC_STRPOOL_H__ #define __SMCC_STRPOOL_H__
@ -5,13 +12,43 @@
#include <lib/rt/rt_alloc.h> #include <lib/rt/rt_alloc.h>
#include <lib/utils/ds/hashtable.h> #include <lib/utils/ds/hashtable.h>
/**
* @struct strpool_t
* @brief 字符串池上下文
*
* 组合哈希表和专用内存分配器实现的高效字符串存储池
*/
typedef struct strpool { typedef struct strpool {
hash_table_t ht; // 用于快速查找字符串 hash_table_t ht; /**< 哈希表用于快速查找已存储字符串 */
long_alloc_t stralloc; // 专门用于字符串存储的分配器 long_alloc_t stralloc; /**< 长块分配器优化小字符串内存管理 */
} strpool_t; } strpool_t;
/**
* @brief 初始化字符串池
* @param pool 字符串池实例指针
*
* @warning 使用前需确保 hashtable 的 hash_func 和 key_cmp 已正确设置
*/
void init_strpool(strpool_t* pool); void init_strpool(strpool_t* pool);
/**
* @brief 驻留字符串到池中
* @param pool 字符串池实例指针
* @param str 要驻留的 C 字符串
* @return 池中唯一字符串的持久指针
*
* @note 返回值生命周期与字符串池一致
* @note 重复插入相同字符串会返回已有指针
*/
const char* strpool_intern(strpool_t* pool, const char* str); const char* strpool_intern(strpool_t* pool, const char* str);
/**
* @brief 销毁字符串池
* @param pool 字符串池实例指针
*
* @warning 销毁后已获取的字符串指针将失效
* @note 会自动释放所有驻留字符串内存
*/
void strpool_destroy(strpool_t* pool); void strpool_destroy(strpool_t* pool);
#endif // __SMCC_STRPOOL_H__ #endif // __SMCC_STRPOOL_H__

View File

@ -1,7 +1,7 @@
CC = gcc CC = gcc
CFLAGS = -g -Wall -I.. CFLAGS = -g -Wall -I..
LIBS = -Lccompiler -lcc -Lassembler/riscv32 -lasm -Llinker -llk -Lmcode -lmc -L../lib -lcore LIBS = -Lccompiler -lcc -Lassembler/riscv32 -lasm -Llinker -llk -Lmcode -lmc -L../lib -lcore
# CLFAGS += -fsanitize=address CLFAGS += -fsanitize=address
all: smcc all: smcc
smcc: cc asm lib mc lk smcc: cc asm lib mc lk
@ -27,4 +27,4 @@ clean:
make -C assembler/riscv32 clean make -C assembler/riscv32 clean
make -C ccompiler clean make -C ccompiler clean
make -C mcode clean make -C mcode clean
make -C linker clean make -C linker clean

View File

@ -2,7 +2,6 @@ CC = gcc
AR = ar AR = ar
CFLAGS = -g -Wall -I../../.. CFLAGS = -g -Wall -I../../..
# 自动收集所有子模块源文件
EXCLUDE = test*.c EXCLUDE = test*.c
SRCS = $(filter-out $(EXCLUDE), $(wildcard *.c)) SRCS = $(filter-out $(EXCLUDE), $(wildcard *.c))

View File

@ -13,3 +13,17 @@ void init_rv32_prog(rv32_prog_t* prog, strpool_t* strpool) {
init_symtab_asm(&prog->symtab); init_symtab_asm(&prog->symtab);
init_rv32_mcode(&prog->mcode, sizeof(symasm_entry_t)); init_rv32_mcode(&prog->mcode, sizeof(symasm_entry_t));
} }
void asm_from_file(const char* file_name, rv32_prog_t* prog) {
init_rv32_prog(prog, NULL);
rt_file_t* fp = rt.fopen(file_name, "r");
if (fp == NULL) {
LOG_FATAL("Failed to open file %s", file_name);
}
char buf[1024];
rt.fread(buf, 1, sizeof(buf), fp);
}

View File

@ -9,7 +9,7 @@ typedef struct rv32_prog {
symtab_asm_t symtab; symtab_asm_t symtab;
u32_t text_base_address; u32_t text_base_address;
u32_t data_base_address; u32_t data_base_address;
vector_header(data, iptr_t); VECTOR_HEADER(data, iptr_t);
mcode_rv32_t mcode; mcode_rv32_t mcode;
} rv32_prog_t; } rv32_prog_t;

View File

@ -1,37 +1,76 @@
/**
* @file lexer.h
* @brief C语言词法分析器核心数据结构与接口
*/
#ifndef __SMCC_CC_LEXER_H__ #ifndef __SMCC_CC_LEXER_H__
#define __SMCC_CC_LEXER_H__ #define __SMCC_CC_LEXER_H__
#include <lib/core.h> #include <lib/core.h>
#include "token.h" #include "token.h"
#ifndef LEXER_MAX_TOKEN_SIZE #ifndef LEXER_MAX_TOKEN_SIZE
#define LEXER_MAX_TOKEN_SIZE 63 #define LEXER_MAX_TOKEN_SIZE 63 ///< 单个token的最大长度限制
#endif
#ifndef LEXER_BUFFER_SIZE
#define LEXER_BUFFER_SIZE 4095
#endif #endif
#ifndef LEXER_BUFFER_SIZE
#define LEXER_BUFFER_SIZE 4095 ///< 词法分析缓冲区大小
#endif
/**
* @brief 流读取函数原型
* @param dst_buf 目标缓冲区
* @param elem_size 元素大小
* @param count 元素数量
* @param stream 输入流指针
* @return 实际读取的元素数量
*/
typedef int (*lexer_sread_fn)(void *dst_buf, int elem_size, int count, void *stream); typedef int (*lexer_sread_fn)(void *dst_buf, int elem_size, int count, void *stream);
/**
* @brief 词法分析器核心结构体
*
* 封装词法分析所需的状态信息和缓冲区管理
*/
typedef struct cc_lexer { typedef struct cc_lexer {
loc_t loc; loc_t loc; ///< 当前解析位置信息(文件名、行列号等)
char* cur_ptr; // 当前扫描的字符,但是还没有开始扫描 char* cur_ptr; ///< 当前扫描指针(指向尚未处理的字符)
char* end_ptr; // 缓冲区最后一个字符的下一个位置 char* end_ptr; ///< 缓冲区结束指针(指向最后一个有效字符的下一个位置
char buffer[LEXER_BUFFER_SIZE+1]; char buffer[LEXER_BUFFER_SIZE+1]; ///< 字符缓冲区包含NUL终止符
lexer_sread_fn sread; lexer_sread_fn sread; ///< 流读取函数指针
void* stream; void* stream; ///< 输入流对象指针
strpool_t* strpool; ///< 字符串池(用于存储标识符等字符串)
strpool_t* strpool;
} cc_lexer_t; } cc_lexer_t;
/**
* @brief 初始化词法分析器
* @param[out] lexer 要初始化的词法分析器实例
* @param[in] file_name 当前解析的源文件名
* @param[in] stream 输入流对象指针
* @param[in] sread 自定义流读取函数
* @param[in] strpool 字符串池实例
*/
void init_lexer(cc_lexer_t* lexer, const char* file_name, void* stream, void init_lexer(cc_lexer_t* lexer, const char* file_name, void* stream,
lexer_sread_fn sread, strpool_t* strpool); lexer_sread_fn sread, strpool_t* strpool);
// pure token getter it will included empty token like TOKEN_BLANK /**
* @brief 获取原始token
* @param[in] lexer 词法分析器实例
* @param[out] token 输出token存储位置
*
* 此函数会返回所有类型的token包括空白符等无效token
*/
void get_token(cc_lexer_t* lexer, tok_t* token); void get_token(cc_lexer_t* lexer, tok_t* token);
// get_token maybe got invalid (with parser as TOKEN_BLANK) /**
* @brief 获取有效token
* @param[in] lexer 词法分析器实例
* @param[out] token 输出token存储位置
*
* 此函数会自动跳过空白符等无效token返回对语法分析有意义的token
*/
void get_valid_token(cc_lexer_t* lexer, tok_t* token); void get_valid_token(cc_lexer_t* lexer, tok_t* token);
#endif #endif

View File

@ -84,10 +84,10 @@ typedef struct ast_node {
union { union {
void *children[6]; void *children[6];
struct { struct {
vector_header(children, struct ast_node *); VECTOR_HEADER(children, struct ast_node *);
} root; } root;
struct { struct {
vector_header(children, struct ast_node *); VECTOR_HEADER(children, struct ast_node *);
} block; } block;
struct { struct {
symtab_key_t key; symtab_key_t key;
@ -95,7 +95,7 @@ typedef struct ast_node {
tok_t tok; tok_t tok;
} syms; } syms;
struct { struct {
vector_header(params, struct ast_node *); VECTOR_HEADER(params, struct ast_node *);
} params; } params;
struct { struct {
struct ast_node * name; struct ast_node * name;

View File

@ -38,21 +38,21 @@ typedef struct ir_node ir_node_t;
typedef struct ir_bblock { typedef struct ir_bblock {
const char *label; const char *label;
vector_header(instrs, ir_node_t*); VECTOR_HEADER(instrs, ir_node_t*);
// ir_arr_t used_by; // ir_arr_t used_by;
} ir_bblock_t; // basic block } ir_bblock_t; // basic block
typedef struct { typedef struct {
const char *name; const char *name;
ir_type_t *type; ir_type_t *type;
vector_header(params, ir_node_t*); VECTOR_HEADER(params, ir_node_t*);
vector_header(bblocks, ir_bblock_t*); VECTOR_HEADER(bblocks, ir_bblock_t*);
} ir_func_t; } ir_func_t;
typedef struct { typedef struct {
vector_header(global, ir_node_t*); VECTOR_HEADER(global, ir_node_t*);
vector_header(funcs, ir_func_t*); VECTOR_HEADER(funcs, ir_func_t*);
vector_header(extern_funcs, ir_func_t*); VECTOR_HEADER(extern_funcs, ir_func_t*);
} ir_prog_t; } ir_prog_t;
typedef enum ir_node_tag { typedef enum ir_node_tag {
@ -72,7 +72,7 @@ typedef enum ir_node_tag {
struct ir_node { struct ir_node {
const ir_type_t* type; const ir_type_t* type;
const char* name; const char* name;
vector_header(used_by, ir_node_t*); VECTOR_HEADER(used_by, ir_node_t*);
ir_node_tag_t tag; ir_node_tag_t tag;
union { union {
struct { struct {
@ -141,7 +141,7 @@ struct ir_node {
} jump; } jump;
struct { struct {
ir_func_t* callee; ir_func_t* callee;
vector_header(args, ir_node_t*); VECTOR_HEADER(args, ir_node_t*);
} call; } call;
struct { struct {
ir_node_t* ret_val; ir_node_t* ret_val;

View File

@ -47,7 +47,7 @@ rv32_prog_t* link_rv32_prog(rv32_prog_t* progs[]) {
if (paddr == NULL) { if (paddr == NULL) {
paddr = symtab_asm_get(&symtab, rinstr->target); paddr = symtab_asm_get(&symtab, rinstr->target);
if (paddr == NULL) { if (paddr == NULL) {
LOG_FATAL("linker: %s not found", ((symasm_entry_t*)rinstr)->name); LOG_FATAL("linker: %s not found", ((symasm_entry_t*)rinstr->target)->name);
} }
addr = *paddr; addr = *paddr;
} else { } else {

View File

@ -1,7 +1,7 @@
CC = gcc CC = gcc
AR = ar AR = ar
CFLAGS = -g -Wall -I../.. CFLAGS = -g -Wall -I../..
MODULES = riscv32 MODULES = . riscv32
EXCLUDE = test*.c EXCLUDE = test*.c
SRCS = $(filter-out $(EXCLUDE), $(wildcard $(addsuffix /*.c,$(MODULES)))) SRCS = $(filter-out $(EXCLUDE), $(wildcard $(addsuffix /*.c,$(MODULES))))
@ -14,4 +14,4 @@ libmc.a: $(OBJS)
$(CC) $(CFLAGS) -c -o $@ $< $(CC) $(CFLAGS) -c -o $@ $<
clean: clean:
rm -f libmc.a $(OBJS) rm -f libmc.a $(OBJS)

48
src/mcode/reloc_symtab.c Normal file
View File

@ -0,0 +1,48 @@
#include "reloc_symtab.h"
// /* append label */
// static inline int
// rv32_append_label(mcode_rv32_t* prog, void* label, u32_t offset) {
// // prog->symtab
// symtab_asm_put(&prog->symtab, label, offset);
// return 0;
// }
// static u32_t hash_func(const symasm_entry_t* key) {
// return rt_strhash(key->name);
// }
// static int cmp_func(const symasm_entry_t* k1, const symasm_entry_t* k2) {
// return rt_strcmp(k1->name, k2->name);
// }
// void init_symtab_asm(symtab_asm_t* symtab) {
// init_hashtable(&symtab->symtab);
// symtab->symtab.hash_func = (u32_t(*)(const void*))hash_func;
// symtab->symtab.key_cmp = (int(*)(const void*, const void*))cmp_func;
// }
// void symtab_asm_put(symtab_asm_t* symtab, symasm_entry_t* _entry, u32_t address) {
// // FIXME maybe memory leak
// u32_t* addr = salloc_alloc(sizeof(u32_t));
// if (addr == NULL) {
// LOG_FATAL("salloc_alloc failure");
// }
// symasm_entry_t* entry = salloc_alloc(sizeof(symasm_entry_t));
// if (entry == NULL) LOG_FATAL("malloc failure");
// *entry = *_entry;
// *addr = address;
// void* ret = hashtable_set(&symtab->symtab, entry, addr);
// if (ret != NULL) {
// LOG_ERROR("Symbol %s already exists", entry->name);
// }
// }
// u32_t* symtab_asm_get(symtab_asm_t* symtab, symasm_entry_t* entry) {
// u32_t* addr = hashtable_get(&symtab->symtab, entry);
// return addr;
// }
// void symtab_asm_destroy(symtab_asm_t* symtab) {
// hashtable_destory(&symtab->symtab);
// }

27
src/mcode/reloc_symtab.h Normal file
View File

@ -0,0 +1,27 @@
#ifndef __SMCC_RELOC_SYMTAB_H__
#define __SMCC_RELOC_SYMTAB_H__
// Relocation Symbol Table
#include <lib/core.h>
#include <lib/utils/ds/hashtable.h>
typedef enum reloc_attr {
RELOC_ATTR_GLOBAL,
RELOC_ATTR_LOCAL,
} reloc_attr_t;
typedef struct reloc_entry {
const char* name;
reloc_attr_t attr;
} reloc_entry_t;
typedef struct reloc_symtab {
hash_table_t reloctab;
} reloc_symtab_t;
void init_symtab_asm(reloc_symtab_t* symtab);
void symtab_asm_put(reloc_symtab_t* symtab, reloc_entry_t* entry, u32_t address);
u32_t* symtab_asm_get(reloc_symtab_t* symtab, reloc_entry_t* entry);
void symtab_asm_destroy(reloc_symtab_t* symtab);
#endif

View File

@ -12,8 +12,8 @@ typedef struct rotated_instr {
} rotated_instr_t; } rotated_instr_t;
typedef struct mcode_rv32 { typedef struct mcode_rv32 {
vector_header(rinstrs, rotated_instr_t); VECTOR_HEADER(rinstrs, rotated_instr_t);
vector_header(code, u8_t); VECTOR_HEADER(code, u8_t);
int target_size; int target_size;
} mcode_rv32_t; } mcode_rv32_t;

View File

@ -7,7 +7,7 @@ int main(int argc, char** argv) {
init_lib_core(); init_lib_core();
log_set_level(NULL, LOG_LEVEL_ERROR | LOG_LEVEL_WARN | LOG_LEVEL_FATAL); log_set_level(NULL, LOG_LEVEL_ERROR | LOG_LEVEL_WARN | LOG_LEVEL_FATAL);
const char* infilename = "test.c"; const char* infilename = ".test.c";
const char* outfilename = "flat.bin"; const char* outfilename = "flat.bin";
if (argc >= 2) { if (argc >= 2) {
infilename = argv[1]; infilename = argv[1];

View File

@ -1,52 +0,0 @@
// int main() {
// int a;
// int b;
// a = 1 + 2 * 3;
// b = 7;
// a = a - b + 1;
// return a;
// }
// // int main() {
// // int x = 10;
// // x = x + 1;
// // return x;
// // }
// int main(void) {
// int a;
// a = 1;
// if (a) {
// a = 1;
// } else {
// a = 2;
// }
// return a;
// }
// int add(int, int);
// int main(void) {
// return add(1, 2);
// }
// int add(int a, int b) {
// return a + b;
// }
// int factorial(int num);
// int main() {
// int num = 5;
// int result = factorial(num);
// // printf("%d", result);
// return result;
// }
// int factorial(int num) {
// if (num == 0) {
// return 1;
// } else {
// return num * factorial(num - 1);
// }
// }
int main() {
return 65536;
}