Compare commits

...

7 Commits

Author SHA1 Message Date
zzy
2a90e165a5 feat(ast): 重构AST转储功能并创建AST到IR转换器
- 重构ast_dump.c中的宏定义,简化PRINT_VALUE、PRINT_NODE、
  PRINT_QUOTED_VALUE等宏的实现
- 移除冗余的PRINT_COLORED宏定义
- 统一使用SCC_TREE_DUMP_PRINT_PURE和SCC_TREE_DUMP_PRINT_AROUND
  宏进行转储输出
- 在dump_stmt_impl函数中优化节点转储逻辑,统一使用end_node_dump
  替代手动换行
- 添加对未知节点类型的警告日志输出
- 创建新的ast2ir模块,包含AST到IR的基本转换功能
- 实现ast_type_to_ir_type、ast_expr_to_ir、ast_stmt_to_ir、
  ast_decl_to_ir等核心转换函数
- 更新IR库依赖配置,添加scc_utils和tree_dump依赖
- 新增IR基础接口定义文件ir_base.h和IR构建器接口ir_builder.h
2026-01-30 23:01:55 +08:00
zzy
c8bf98525d chore(build): 更新构建脚本和配置文件
- 修改justfile中的构建命令,将build-lexer重命名为build_lexer
- 添加count命令用于统计代码行数
- 更新docs命令依赖关系

feat(docs): 完善README文档内容

- 更新项目名称为Simple C Compiler,简化为`scc`
- 添加详细的构建说明,介绍cbuild构建工具
- 补充标准C语言文档链接
- 重新组织项目特点描述

refactor(tree_dump): 修复未使用的返回值警告

- 在tree_dump_pop_level函数中添加(void)强制转换
- 解决scc_vec_pop返回值未被使用的问题

chore(gitignore): 添加新的忽略文件类型

- 增加.dot和.svg文件类型的忽略规则
- 保持.gitignore文件结构清晰
2026-01-30 14:18:07 +08:00
zzy
135e874a76 feat(ast): 重构AST转储功能并添加tree_dump依赖
- 添加tree_dump库作为依赖项到ast模块
- 将ast_dump.h中的转储上下文结构替换为tree_dump.h中的统一实现
- 更新scc_ast_block_item_vec_t类型定义,支持stmt或decl的泛型指针
- 移除ast_dump.c中重复的缩进和上下文管理代码,使用tree_dump提供的功能
- 修改dump函数参数类型从scc_ast_dump_ctx_t为scc_tree_dump_ctx_t
- 在libs目录下新增tree_dump库,包含完整的树形结构转储功能
2026-01-28 17:29:56 +08:00
zzy
79ee7a657a feat(ast): 添加AST定义和dump工具头文件
新增libs/ast模块的基础定义文件,包括:
- AST节点类型枚举定义,涵盖声明、语句、表达式、类型等各类节点
- AST操作符枚举,定义所有二元、一元、逻辑、算术等操作符
- AST节点结构体定义,包含表达式、语句、声明、类型等具体实现
- AST dump工具接口,支持树形结构输出和颜色显示
- 语义分析回调函数类型定义,为后续语义分析提供基础
2026-01-28 15:44:59 +08:00
zzy
e1cd8c5206 feat(lexer): 添加SCC语言扩展关键字支持并重构标准定义
- 将SCC_CEXT_ASM重命名为SCC_CEXT_SCC以更好地反映扩展类型
- 为asm关键字添加SCC_CEXT_SCC标准标识
- 新增atomic、auto、bool、complex四个关键字及其对应的token类型
- 所有新关键字都标记为SCC_CEXT_SCC扩展标准

fix(lexer): 修复数字字面量解析中的类型不匹配问题

- 将token->value.n更正为token->value.u以正确存储解析结果
- 统一了词法分析器中数值解析的字段访问

refactor(log): 重构日志系统API设计并增强功能

- 将日志处理器接口从void返回改为int返回类型
- 新增函数名记录功能,通过__func__宏获取当前函数名
- 引入可变参数支持,允许格式化字符串传递
- 重构内部宏实现,使用SCC_LOG_IMPL统一处理逻辑
- 改进缓冲区管理,优化日志消息格式化流程
- 重命名头文件保护宏从__SCC_LOG_H__到__SCC_LOG_IMPL_H__
- 替换snprintf为vsnprintf以支持可变参数处理
- 更新断言宏实现,提供更清晰的错误信息格式
2026-01-28 15:44:24 +08:00
zzy
84cff78b86 feat(lexer): 在换行符处理时添加流回退功能
在词法分析器中遇到换行符时,添加对 scc_probe_stream_back 的调用,
以确保流探针位置正确回退。同时修正了 probe_stream_t 接口定义中的
注释说明,明确 back 函数的作用是后退探针位置而非头指针位置。

修复了内存探针流实现中回退逻辑的边界条件判断,
现在能够正确处理探针位置的回退操作。
2026-01-11 14:20:54 +08:00
zzy
6c801fbb92 refactor(lexer): 移除未使用的期望函数并修复内存分配错误
移除了 scc_lexer_tok_expect 函数,因为它不再被使用。
在 lexer_stream_extend 函数中添加了返回语句,以在内存重新分配失败时正确处理错误。

BREAKING CHANGE: 移除了 scc_lexer_tok_expect 函数
2026-01-10 17:43:31 +08:00
51 changed files with 8616 additions and 326 deletions

4
.gitignore vendored
View File

@@ -32,3 +32,7 @@ build
# external
external/
# dot file and svg file
*.dot
*.svg

View File

@@ -1,15 +1,35 @@
# Simple Models C Compiler
# Simple C Compiler
> Smaller Compiler(SMCC)
> `scc`
This is a simple C compiler that generates executable code from a simple c99 sub programming language. The language supports basic operations such as arithmetic, logical, conditional statements and if else while for switch case statements and function calls and system calls.
这是一个简单的C语言编译器可以从C99子集编程语言生成可执行代码。该语言支持基本操作如算术运算、逻辑运算、条件语句if/else)、循环语句(while/for)、分支语句(switch/case、函数调用以及内联汇编调用asm
## Features
## Builder
- 隔离标准库
该编译器使用`cbuild` 构建,设计思路来源于`rust`的构建工具`cargo`,以默认行为代替掉`make``cmake`等构建工具。
- 轻量化
> 由于整个项目除了测试代码,完全没有任何依赖,真正做到`0依赖`,所以无需复杂的依赖管理
TODO 未来构建工具本身也会使用c或者lua等可轻松自举的系统重构
- 模块化
### [cbuild](./tools/cbuild/cbuild.py)
- 自举构建
常用命令:
- 构建项目: `cbuild build`
- 运行程序: `cbuild run`
- 运行测试: `cbuild test`
- 清理构建产物: `cbuild clean`
- 查看依赖树: `cbuild tree`
## 标准C语言文档链接
- [open-std](https://www.open-std.org/)
- [C - Project status and milestones](https://www.open-std.org/JTC1/SC22/WG14/www/projects#9899)
- [ISO/IEC 9899:1999](https://www.open-std.org/JTC1/SC22/WG14/www/docs/n1256.pdf)
## 项目特点
- **隔离标准库**: 不直接依赖标准库实现,提高可移植性
- **轻量化**: 专注于核心功能,减少冗余组件
- **模块化**: 采用模块化设计,易于扩展和维护
- **自举构建**: 支持通过自身编译器构建项目

View File

@@ -1,11 +1,15 @@
list:
just --list
build-lexer:
python build.py build -p libs/lexer
build-docs:
build_docs:
doxygen Doxyfile
docs: build-docs
docs: build_docs
python -m http.server -d docs/html
count:
# you need download `tokei` it can download by cargo
tokei libs runtime src -e tests
build_lexer:
python ./tools/cbuild/cbuild.py --path libs/lexer build

9
libs/ast/cbuild.toml Normal file
View File

@@ -0,0 +1,9 @@
[package]
name = "scc_ast"
version = "0.1.0"
authors = []
description = ""
dependencies = [{ name = "tree_dump", path = "../tree_dump" }]
# features = {}
# default_features = []

442
libs/ast/include/ast_def.h Normal file
View File

@@ -0,0 +1,442 @@
#ifndef __SCC_AST_DEF_H__
#define __SCC_AST_DEF_H__
#include <scc_core.h>
/**
* @brief AST 节点类型枚举
*/
typedef enum {
// 声明
scc_ast_decl_t_BEGIN, // 声明开始
SCC_AST_DECL_VAR, // 变量声明
SCC_AST_DECL_FUNC, // 函数声明
SCC_AST_DECL_PARAM, // 参数声明
SCC_AST_DECL_STRUCT, // 结构体声明
SCC_AST_DECL_UNION, // 联合声明
SCC_AST_DECL_ENUM, // 枚举声明
SCC_AST_DECL_TYPEDEF, // typedef 声明
scc_ast_decl_t_END, // 声明结束
// 语句
scc_ast_stmt_t_BEGIN, // 语句开始
SCC_AST_STMT_COMPOUND, // 复合语句 { ... }
SCC_AST_STMT_EXPR, // 表达式语句
SCC_AST_STMT_IF, // if 语句
SCC_AST_STMT_WHILE, // while 语句
SCC_AST_STMT_DO_WHILE, // do-while 语句
SCC_AST_STMT_FOR, // for 语句
SCC_AST_STMT_SWITCH, // switch 语句
SCC_AST_STMT_CASE, // case 语句
SCC_AST_STMT_DEFAULT, // default 语句
SCC_AST_STMT_BREAK, // break 语句
SCC_AST_STMT_CONTINUE, // continue 语句
SCC_AST_STMT_RETURN, // return 语句
SCC_AST_STMT_GOTO, // goto 语句
SCC_AST_STMT_LABEL, // 标签语句
scc_ast_stmt_t_END, // 结束语句
// 表达式
scc_ast_expr_t_BEGIN, // 表达式开始
SCC_AST_EXPR_BINARY, // 二元运算
SCC_AST_EXPR_UNARY, // 一元运算
SCC_AST_EXPR_COND, // 条件表达式 ?:
SCC_AST_EXPR_CALL, // 函数调用
SCC_AST_EXPR_ARRAY_SUBSCRIPT, // 数组下标
SCC_AST_EXPR_MEMBER, // 成员访问 .
SCC_AST_EXPR_PTR_MEMBER, // 指针成员访问 ->
SCC_AST_EXPR_CAST, // 类型转换
SCC_AST_EXPR_SIZE_OF, // sizeof
SCC_AST_EXPR_ALIGN_OF, // _Alignof
SCC_AST_EXPR_COMPOUND_LITERAL, // 复合字面量
// 字面量
SCC_AST_EXPR_INT_LITERAL, // 整数字面量
SCC_AST_EXPR_FLOAT_LITERAL, // 浮点字面量
SCC_AST_EXPR_CHAR_LITERAL, // 字符字面量
SCC_AST_EXPR_STRING_LITERAL, // 字符串字面量
// 标识符
SCC_AST_EXPR_IDENTIFIER, // 标识符
scc_ast_expr_t_END, // 表达式结束
// 类型
scc_ast_type_t_BEGIN, // 类型开始
SCC_AST_TYPE_BUILTIN, // 内置类型
SCC_AST_TYPE_POINTER, // 指针类型
SCC_AST_TYPE_ARRAY, // 数组类型
SCC_AST_TYPE_FUNCTION, // 函数类型
SCC_AST_TYPE_STRUCT, // 结构体类型
SCC_AST_TYPE_UNION, // 联合类型
SCC_AST_TYPE_ENUM, // 枚举类型
SCC_AST_TYPE_TYPEDEF, // typedef 类型
scc_ast_type_t_END, // 类型结束
// 其他
scc_ast_translation_unit_t_BEGIN,
SCC_AST_TRANSLATION_UNIT, // 翻译单元(根节点)
scc_ast_translation_unit_t_END,
} scc_ast_node_type_t;
typedef struct {
scc_ast_node_type_t type;
scc_pos_t loc;
} scc_ast_node_t;
#define SCC_AST_CAST_TO(kind, expr) \
((kind *)(Assert(((scc_ast_node_t *)expr)->type > kind##_BEGIN && \
((scc_ast_node_t *)expr)->type < kind##_END), \
(expr)))
#define SCC_AST_IS_A(kind, expr) \
((expr) && (((scc_ast_node_t *)expr)->type > kind##_BEGIN && \
((scc_ast_node_t *)expr)->type < kind##_END))
/**
* @brief 内置类型枚举
*/
typedef enum {
TYPE_VOID,
TYPE_CHAR,
TYPE_SHORT,
TYPE_INT,
TYPE_LONG,
TYPE_LONG_LONG,
TYPE_FLOAT,
TYPE_DOUBLE,
TYPE_LONG_DOUBLE,
TYPE_BOOL,
TYPE_COMPLEX_FLOAT,
TYPE_COMPLEX_DOUBLE,
TYPE_COMPLEX_LONG_DOUBLE,
} scc_ast_builtin_type_t;
/**
* @brief 限定符
*/
typedef struct {
// storage-class-specifier
cbool is_typedef;
cbool is_extern;
cbool is_static;
cbool is_auto;
cbool is_register;
// type-qualifier
cbool is_const;
cbool is_volatile;
cbool is_restrict;
cbool is_atomic;
// function-specifier
cbool is_inline;
} scc_ast_decl_specifier_t;
// 前向声明
typedef struct scc_ast_type scc_ast_type_t;
typedef struct scc_ast_expr scc_ast_expr_t;
typedef struct scc_ast_stmt scc_ast_stmt_t;
typedef struct scc_ast_decl scc_ast_decl_t;
typedef SCC_VEC(scc_ast_type_t *) scc_ast_type_vec_t;
typedef SCC_VEC(scc_ast_expr_t *) scc_ast_expr_vec_t;
typedef SCC_VEC(scc_ast_stmt_t *) scc_ast_stmt_vec_t;
typedef SCC_VEC(scc_ast_decl_t *) scc_ast_decl_vec_t;
// 通过指针实现泛型 only stmt or decl
typedef SCC_VEC(scc_ast_node_t *) scc_ast_block_item_vec_t;
/**
* @brief 类型表示
*/
struct scc_ast_type {
scc_ast_node_t base;
union {
struct {
scc_ast_builtin_type_t builtin;
scc_ast_decl_specifier_t quals;
} builtin;
struct {
scc_ast_type_t *pointee;
scc_ast_decl_specifier_t quals;
} pointer;
struct {
scc_ast_type_t *element;
scc_ast_expr_t *size; // 可为 null <=> 不定长数组
} array;
struct {
scc_ast_type_t *return_type;
scc_ast_type_vec_t param_types;
cbool is_variadic;
} function;
struct {
const char *name;
scc_ast_decl_vec_t fields; // 结构体/联合字段
} record;
struct {
const char *name;
scc_ast_expr_vec_t enumerators; // 枚举项
} enumeration;
struct {
const char *name;
scc_ast_type_t *underlying;
} typedef_type;
};
};
/**
* @brief AST 操作符枚举
* 这个枚举定义了所有在AST中使用的操作符与词法token分离
*/
typedef enum scc_ast_expr_op {
/* 无操作符 */
SCC_AST_OP_NONE = 0,
/* 赋值操作符 */
SCC_AST_OP_ASSIGN, // =
SCC_AST_OP_ASSIGN_ADD, // +=
SCC_AST_OP_ASSIGN_SUB, // -=
SCC_AST_OP_ASSIGN_MUL, // *=
SCC_AST_OP_ASSIGN_DIV, // /=
SCC_AST_OP_ASSIGN_MOD, // %=
SCC_AST_OP_ASSIGN_AND, // &=
SCC_AST_OP_ASSIGN_XOR, // ^=
SCC_AST_OP_ASSIGN_OR, // |=
SCC_AST_OP_ASSIGN_LSHIFT, // <<=
SCC_AST_OP_ASSIGN_RSHIFT, // >>=
/* 条件操作符 */
SCC_AST_OP_CONDITIONAL, // ?:
/* 逻辑操作符 */
SCC_AST_OP_LOGICAL_OR, // ||
SCC_AST_OP_LOGICAL_AND, // &&
/* 位操作符 */
SCC_AST_OP_BITWISE_OR, // |
SCC_AST_OP_BITWISE_XOR, // ^
SCC_AST_OP_BITWISE_AND, // &
/* 相等性操作符 */
SCC_AST_OP_EQUAL, // ==
SCC_AST_OP_NOT_EQUAL, // !=
/* 关系操作符 */
SCC_AST_OP_LESS, // <
SCC_AST_OP_GREATER, // >
SCC_AST_OP_LESS_EQUAL, // <=
SCC_AST_OP_GREATER_EQUAL, // >=
/* 移位操作符 */
SCC_AST_OP_LEFT_SHIFT, // <<
SCC_AST_OP_RIGHT_SHIFT, // >>
/* 算术操作符 */
SCC_AST_OP_ADD, // +
SCC_AST_OP_SUB, // -
SCC_AST_OP_MUL, // *
SCC_AST_OP_DIV, // /
SCC_AST_OP_MOD, // %
/* 一元操作符 */
SCC_AST_OP_UNARY_PLUS, // + (一元)
SCC_AST_OP_UNARY_MINUS, // - (一元)
SCC_AST_OP_ADDRESS_OF, // &
SCC_AST_OP_INDIRECTION, // *
SCC_AST_OP_BITWISE_NOT, // ~
SCC_AST_OP_LOGICAL_NOT, // !
SCC_AST_OP_PREFIX_INCREMENT, // ++ (前缀)
SCC_AST_OP_PREFIX_DECREMENT, // -- (前缀)
SCC_AST_OP_POSTFIX_INCREMENT, // ++ (后缀)
SCC_AST_OP_POSTFIX_DECREMENT, // -- (后缀)
/* 成员访问 */
SCC_AST_OP_MEMBER_ACCESS, // .
SCC_AST_OP_PTR_MEMBER_ACCESS, // ->
} scc_ast_expr_op_t;
/**
* @brief 表达式节点
*/
struct scc_ast_expr {
scc_ast_node_t base;
union {
// 二元运算
struct {
scc_ast_expr_op_t op;
scc_ast_expr_t *lhs;
scc_ast_expr_t *rhs;
} binary;
// 一元运算
struct {
scc_ast_expr_op_t op;
scc_ast_expr_t *operand;
} unary;
// 条件表达式
struct {
scc_ast_expr_t *cond;
scc_ast_expr_t *then_expr;
scc_ast_expr_t *else_expr;
} cond;
// 函数调用
struct {
scc_ast_expr_t *callee;
scc_ast_expr_vec_t args;
} call;
// 数组下标
struct {
scc_ast_expr_t *array;
scc_ast_expr_t *index;
} subscript;
// 成员访问
struct {
scc_ast_expr_t *base;
const char *member_name;
} member;
// 指针成员访问
struct {
scc_ast_expr_t *base;
const char *member_name;
} ptr_member;
// 类型转换
struct {
scc_ast_type_t *type;
scc_ast_expr_t *expr;
} cast;
// sizeof / _Alignof / ...
union {
scc_ast_type_t *type;
scc_ast_expr_t *expr;
} attr_of;
// 复合字面量
struct {
scc_ast_type_t *type;
scc_ast_expr_vec_t init_list;
} compound_literal;
// 字面量
struct {
scc_cvalue_t value;
} literal;
// 标识符
struct {
const char *name;
} identifier;
};
};
/**
* @brief 语句节点
*/
struct scc_ast_stmt {
scc_ast_node_t base;
union {
// 复合语句
struct {
scc_ast_block_item_vec_t block_items; // decl or stmt
} compound;
// 表达式语句
struct {
scc_ast_expr_t *expr;
} expr;
// if 语句
struct {
scc_ast_expr_t *cond;
scc_ast_stmt_t *then_stmt;
scc_ast_stmt_t *opt_else_stmt; // stmt or null
} if_stmt;
// while 语句
struct {
scc_ast_expr_t *cond;
scc_ast_stmt_t *body;
} while_stmt;
// do-while 语句
struct {
scc_ast_stmt_t *body;
scc_ast_expr_t *cond;
} do_while_stmt;
// for 语句
struct {
scc_ast_type_t *init; // expr or decl or null
scc_ast_expr_t *cond; // 可为 null
scc_ast_expr_t *iter; // 可为 null
scc_ast_stmt_t *body;
} for_stmt;
// switch 语句
struct {
scc_ast_expr_t *cond;
scc_ast_stmt_t *body;
} switch_stmt;
// case 语句
struct {
scc_ast_expr_t *expr;
scc_ast_stmt_t *stmt;
} case_stmt;
// default 语句
struct {
scc_ast_stmt_t *stmt;
} default_stmt;
// break/continue
struct {
// 无额外字段
} jump;
// return 语句
struct {
scc_ast_expr_t *expr; // 可为 NULL
} return_stmt;
// goto 语句
struct {
const char *label;
} goto_stmt;
// 标签语句
struct {
const char *label;
scc_ast_stmt_t *stmt;
} label_stmt;
};
};
/**
* @brief 声明节点
*/
struct scc_ast_decl {
scc_ast_node_t base;
union {
// 变量声明
struct {
const char *name;
scc_ast_type_t *type;
scc_ast_expr_t *init; // 可为 NULL
} var;
// 函数声明
struct {
const char *name;
scc_ast_type_t *type; // 函数类型
scc_ast_stmt_t *body; // 可为 NULL只有声明 or
} func;
// 参数声明
struct {
const char *name;
scc_ast_type_t *type;
} param;
// 结构体/联合声明
struct {
const char *name;
scc_ast_decl_vec_t fields;
} record;
// 枚举声明
struct {
const char *name;
scc_ast_expr_vec_t enumerators;
} enumeration;
// typedef 声明
struct {
const char *name;
scc_ast_type_t *type;
} typedef_decl;
};
};
/**
* @brief 翻译单元节点(根节点)
*/
typedef struct scc_ast_translation_unit {
scc_ast_node_t base;
scc_ast_decl_vec_t declarations;
} scc_ast_translation_unit_t;
#endif /* __SCC_AST_DEF_H__ */

View File

@@ -0,0 +1,20 @@
/**
* @file ast_dump.h
* @brief AST dump 工具,支持多种输出格式(插件化设计)
*/
#ifndef __SCC_AST_DUMP_H__
#define __SCC_AST_DUMP_H__
#include "ast_def.h"
#include <tree_dump.h>
/**
* @brief 以指定格式 dump AST
*
* @param node AST 节点(可以是任意类型的节点)
* @param ctx dump 上下文
*/
void scc_ast_dump_node(scc_tree_dump_ctx_t *ctx, const scc_ast_node_t *node);
#endif /* __SCC_AST_DUMP_H__ */

View File

@@ -0,0 +1,23 @@
#ifndef __SCC_AST_H__
#define __SCC_AST_H__
#include "ast_def.h"
/**
* @brief 语义分析回调函数类型
*/
typedef void (*scc_sema_callback_t)(void *context,
scc_ast_node_type_t node_type, void *node);
/**
* @brief 语义分析回调集合
*/
typedef struct scc_sema_callbacks {
scc_sema_callback_t on_decl;
scc_sema_callback_t on_stmt;
scc_sema_callback_t on_expr;
scc_sema_callback_t on_type;
void *context;
} scc_sema_callbacks_t;
#endif /* __SCC_AST_H__ */

716
libs/ast/src/ast_dump.c Normal file
View File

@@ -0,0 +1,716 @@
/**
* @file ast_dump.c
* @brief AST dump 实现
*/
#include <ast_dump.h>
#define PRINT_VALUE(ctx, fmt, value) \
SCC_TREE_DUMP_PRINT_PURE(ctx, ctx->value_color, fmt, value)
#define PRINT_NODE(ctx, name, value) \
SCC_TREE_DUMP_PRINT_PURE(ctx, ctx->node_color, "%s", name)
#define PRINT_QUOTED_VALUE(ctx, str) \
SCC_TREE_DUMP_PRINT_AROUND(ctx, ctx->value_color, "'", "%s", str)
// 获取节点类型的字符串表示
static const char *get_node_type_str(scc_ast_node_type_t type) {
switch (type) {
// 声明类型
case SCC_AST_DECL_VAR:
return "VarDecl";
case SCC_AST_DECL_FUNC:
return "FuncDecl";
case SCC_AST_DECL_PARAM:
return "ParamDecl";
case SCC_AST_DECL_STRUCT:
return "StructDecl";
case SCC_AST_DECL_UNION:
return "UnionDecl";
case SCC_AST_DECL_ENUM:
return "EnumDecl";
case SCC_AST_DECL_TYPEDEF:
return "TypedefDecl";
// 语句类型
case SCC_AST_STMT_COMPOUND:
return "CompoundStmt";
case SCC_AST_STMT_EXPR:
return "ExprStmt";
case SCC_AST_STMT_IF:
return "IfStmt";
case SCC_AST_STMT_WHILE:
return "WhileStmt";
case SCC_AST_STMT_DO_WHILE:
return "DoStmt";
case SCC_AST_STMT_FOR:
return "ForStmt";
case SCC_AST_STMT_SWITCH:
return "SwitchStmt";
case SCC_AST_STMT_CASE:
return "CaseStmt";
case SCC_AST_STMT_DEFAULT:
return "DefaultStmt";
case SCC_AST_STMT_BREAK:
return "BreakStmt";
case SCC_AST_STMT_CONTINUE:
return "ContinueStmt";
case SCC_AST_STMT_RETURN:
return "ReturnStmt";
case SCC_AST_STMT_GOTO:
return "GotoStmt";
case SCC_AST_STMT_LABEL:
return "LabelStmt";
// 表达式类型
case SCC_AST_EXPR_BINARY:
return "BinaryOperator";
case SCC_AST_EXPR_UNARY:
return "UnaryOperator";
case SCC_AST_EXPR_COND:
return "ConditionalOperator";
case SCC_AST_EXPR_CALL:
return "CallExpr";
case SCC_AST_EXPR_ARRAY_SUBSCRIPT:
return "ArraySubscriptExpr";
case SCC_AST_EXPR_MEMBER:
return "MemberExpr";
case SCC_AST_EXPR_PTR_MEMBER:
return "PtrMemberExpr";
case SCC_AST_EXPR_CAST:
return "CastExpr";
case SCC_AST_EXPR_SIZE_OF:
return "SizeOfExpr";
case SCC_AST_EXPR_ALIGN_OF:
return "AlignOfExpr";
case SCC_AST_EXPR_COMPOUND_LITERAL:
return "CompoundLiteralExpr";
case SCC_AST_EXPR_INT_LITERAL:
return "IntegerLiteral";
case SCC_AST_EXPR_FLOAT_LITERAL:
return "FloatingLiteral";
case SCC_AST_EXPR_CHAR_LITERAL:
return "CharacterLiteral";
case SCC_AST_EXPR_STRING_LITERAL:
return "StringLiteral";
case SCC_AST_EXPR_IDENTIFIER:
return "DeclRefExpr";
// 类型类型
case SCC_AST_TYPE_BUILTIN:
return "BuiltinType";
case SCC_AST_TYPE_POINTER:
return "PointerType";
case SCC_AST_TYPE_ARRAY:
return "ArrayType";
case SCC_AST_TYPE_FUNCTION:
return "FunctionType";
case SCC_AST_TYPE_STRUCT:
return "RecordType";
case SCC_AST_TYPE_UNION:
return "RecordType";
case SCC_AST_TYPE_ENUM:
return "EnumType";
case SCC_AST_TYPE_TYPEDEF:
return "TypedefType";
// 根节点
case SCC_AST_TRANSLATION_UNIT:
return "TranslationUnitDecl";
default:
return "UnknownNode";
}
}
// 获取内置类型名称
static const char *get_builtin_type_str(scc_ast_builtin_type_t type) {
switch (type) {
case TYPE_VOID:
return "void";
case TYPE_CHAR:
return "char";
case TYPE_SHORT:
return "short";
case TYPE_INT:
return "int";
case TYPE_LONG:
return "long";
case TYPE_LONG_LONG:
return "long long";
case TYPE_FLOAT:
return "float";
case TYPE_DOUBLE:
return "double";
case TYPE_LONG_DOUBLE:
return "long double";
case TYPE_BOOL:
return "_Bool";
case TYPE_COMPLEX_FLOAT:
return "float _Complex";
case TYPE_COMPLEX_DOUBLE:
return "double _Complex";
case TYPE_COMPLEX_LONG_DOUBLE:
return "long double _Complex";
default:
return "<unknown>";
}
}
// 获取操作符字符串
static const char *get_op_str(scc_ast_expr_op_t op) {
switch (op) {
case SCC_AST_OP_ASSIGN:
return "=";
case SCC_AST_OP_ASSIGN_ADD:
return "+=";
case SCC_AST_OP_ASSIGN_SUB:
return "-=";
case SCC_AST_OP_ASSIGN_MUL:
return "*=";
case SCC_AST_OP_ASSIGN_DIV:
return "/=";
case SCC_AST_OP_ASSIGN_MOD:
return "%=";
case SCC_AST_OP_ASSIGN_AND:
return "&=";
case SCC_AST_OP_ASSIGN_XOR:
return "^=";
case SCC_AST_OP_ASSIGN_OR:
return "|=";
case SCC_AST_OP_ASSIGN_LSHIFT:
return "<<=";
case SCC_AST_OP_ASSIGN_RSHIFT:
return ">>=";
case SCC_AST_OP_CONDITIONAL:
return "? :";
case SCC_AST_OP_LOGICAL_OR:
return "||";
case SCC_AST_OP_LOGICAL_AND:
return "&&";
case SCC_AST_OP_BITWISE_OR:
return "|";
case SCC_AST_OP_BITWISE_XOR:
return "^";
case SCC_AST_OP_BITWISE_AND:
return "&";
case SCC_AST_OP_EQUAL:
return "==";
case SCC_AST_OP_NOT_EQUAL:
return "!=";
case SCC_AST_OP_LESS:
return "<";
case SCC_AST_OP_GREATER:
return ">";
case SCC_AST_OP_LESS_EQUAL:
return "<=";
case SCC_AST_OP_GREATER_EQUAL:
return ">=";
case SCC_AST_OP_LEFT_SHIFT:
return "<<";
case SCC_AST_OP_RIGHT_SHIFT:
return ">>";
case SCC_AST_OP_ADD:
return "+";
case SCC_AST_OP_SUB:
return "-";
case SCC_AST_OP_MUL:
return "*";
case SCC_AST_OP_DIV:
return "/";
case SCC_AST_OP_MOD:
return "%";
case SCC_AST_OP_UNARY_PLUS:
return "+";
case SCC_AST_OP_UNARY_MINUS:
return "-";
case SCC_AST_OP_ADDRESS_OF:
return "&";
case SCC_AST_OP_INDIRECTION:
return "*";
case SCC_AST_OP_BITWISE_NOT:
return "~";
case SCC_AST_OP_LOGICAL_NOT:
return "!";
case SCC_AST_OP_PREFIX_INCREMENT:
return "++";
case SCC_AST_OP_PREFIX_DECREMENT:
return "--";
case SCC_AST_OP_POSTFIX_INCREMENT:
return "++";
case SCC_AST_OP_POSTFIX_DECREMENT:
return "--";
case SCC_AST_OP_MEMBER_ACCESS:
return ".";
case SCC_AST_OP_PTR_MEMBER_ACCESS:
return "->";
default:
return "<op>";
}
}
// 通用的开始节点打印函数
static inline void start_node_dump(scc_ast_node_t *node,
scc_tree_dump_ctx_t *ctx) {
scc_tree_print_indent(ctx);
SCC_TREE_DUMP_PRINT_PURE(ctx, ctx->node_color, "%s",
get_node_type_str(node->type));
}
// 通用的结束节点打印函数
static inline void end_node_dump(scc_tree_dump_ctx_t *ctx) { scc_printf("\n"); }
// 通用的递归转储辅助函数
static inline void dump_child_node(scc_ast_node_t *child,
scc_tree_dump_ctx_t *ctx, cbool is_last) {
if (!child)
return;
scc_vec_push(ctx->stack, is_last);
scc_ast_dump_node(ctx, child);
scc_vec_pop(ctx->stack);
}
// 用于构建复合类型名称的宏
#define BUILD_TYPE_NAME(ctx, prefix, name) \
do { \
if (ctx->use_color) { \
scc_printf("%s'%s%s%s'%s", ctx->value_color, prefix, name, \
ctx->reset_color, ctx->reset_color); \
} else { \
scc_printf("'%s%s'", prefix, name); \
} \
} while (0)
// 递归转储类型
static void dump_type_impl(scc_ast_type_t *type, scc_tree_dump_ctx_t *ctx) {
if (!type)
return;
start_node_dump(&type->base, ctx);
// 根据类型输出特定信息
switch (type->base.type) {
case SCC_AST_TYPE_BUILTIN:
PRINT_QUOTED_VALUE(ctx, get_builtin_type_str(type->builtin.builtin));
break;
case SCC_AST_TYPE_POINTER:
if (type->pointer.pointee &&
type->pointer.pointee->base.type == SCC_AST_TYPE_BUILTIN) {
const char *base_type =
get_builtin_type_str(type->pointer.pointee->builtin.builtin);
if (ctx->use_color) {
scc_printf("%s'%s *'%s", ctx->value_color, base_type,
ctx->reset_color);
} else {
scc_printf("'%s *'", base_type);
}
} else {
PRINT_QUOTED_VALUE(ctx, "pointer");
}
break;
case SCC_AST_TYPE_ARRAY:
PRINT_QUOTED_VALUE(ctx, "array");
break;
case SCC_AST_TYPE_FUNCTION:
PRINT_QUOTED_VALUE(ctx, "function");
break;
case SCC_AST_TYPE_STRUCT:
if (type->record.name) {
BUILD_TYPE_NAME(ctx, "struct ", type->record.name);
} else {
PRINT_QUOTED_VALUE(ctx, "anonymous struct");
}
break;
case SCC_AST_TYPE_UNION:
if (type->record.name) {
BUILD_TYPE_NAME(ctx, "union ", type->record.name);
} else {
PRINT_QUOTED_VALUE(ctx, "anonymous union");
}
break;
case SCC_AST_TYPE_ENUM:
if (type->enumeration.name) {
BUILD_TYPE_NAME(ctx, "enum ", type->enumeration.name);
} else {
PRINT_QUOTED_VALUE(ctx, "anonymous enum");
}
break;
case SCC_AST_TYPE_TYPEDEF:
PRINT_QUOTED_VALUE(ctx, type->typedef_type.name);
break;
default:
break;
}
end_node_dump(ctx);
// 递归转储子节点
switch (type->base.type) {
case SCC_AST_TYPE_POINTER:
dump_child_node((scc_ast_node_t *)type->pointer.pointee, ctx, true);
break;
case SCC_AST_TYPE_ARRAY:
dump_child_node((scc_ast_node_t *)type->array.element, ctx,
type->array.size == NULL);
if (type->array.size) {
dump_child_node((scc_ast_node_t *)type->array.size, ctx, true);
}
break;
default:
break;
}
}
// 递归转储表达式
static void dump_expr_impl(scc_ast_expr_t *expr, scc_tree_dump_ctx_t *ctx) {
if (!expr)
return;
start_node_dump(&expr->base, ctx);
// 根据表达式类型输出特定信息
switch (expr->base.type) {
case SCC_AST_EXPR_BINARY:
PRINT_QUOTED_VALUE(ctx, get_op_str(expr->binary.op));
break;
case SCC_AST_EXPR_UNARY:
PRINT_QUOTED_VALUE(ctx, get_op_str(expr->unary.op));
break;
case SCC_AST_EXPR_INT_LITERAL:
PRINT_VALUE(ctx, " %lld", expr->literal.value.i);
break;
case SCC_AST_EXPR_FLOAT_LITERAL:
PRINT_VALUE(ctx, " %f", expr->literal.value.f);
break;
case SCC_AST_EXPR_CHAR_LITERAL:
PRINT_VALUE(ctx, " '%c'", (char)expr->literal.value.ch);
break;
case SCC_AST_EXPR_STRING_LITERAL:
PRINT_VALUE(ctx, " \"%s\"", expr->literal.value.cstr.data);
break;
case SCC_AST_EXPR_IDENTIFIER:
if (expr->identifier.name) {
PRINT_QUOTED_VALUE(ctx, expr->identifier.name);
}
break;
case SCC_AST_EXPR_SIZE_OF:
case SCC_AST_EXPR_ALIGN_OF:
PRINT_QUOTED_VALUE(ctx, (expr->base.type == SCC_AST_EXPR_SIZE_OF)
? "sizeof"
: "alignof");
break;
default:
break;
}
end_node_dump(ctx);
// 使用辅助函数处理子节点转储
switch (expr->base.type) {
case SCC_AST_EXPR_BINARY:
dump_child_node((scc_ast_node_t *)expr->binary.lhs, ctx, false);
dump_child_node((scc_ast_node_t *)expr->binary.rhs, ctx, true);
break;
case SCC_AST_EXPR_UNARY:
dump_child_node((scc_ast_node_t *)expr->unary.operand, ctx, true);
break;
case SCC_AST_EXPR_COND:
dump_child_node((scc_ast_node_t *)expr->cond.cond, ctx, false);
dump_child_node((scc_ast_node_t *)expr->cond.then_expr, ctx, false);
dump_child_node((scc_ast_node_t *)expr->cond.else_expr, ctx, true);
break;
case SCC_AST_EXPR_CALL:
dump_child_node((scc_ast_node_t *)expr->call.callee, ctx, false);
// 转储参数
for (size_t i = 0; i < expr->call.args.size; i++) {
dump_child_node((scc_ast_node_t *)expr->call.args.data[i], ctx,
i == expr->call.args.size - 1);
}
break;
case SCC_AST_EXPR_ARRAY_SUBSCRIPT:
dump_child_node((scc_ast_node_t *)expr->subscript.array, ctx, false);
dump_child_node((scc_ast_node_t *)expr->subscript.index, ctx, true);
break;
case SCC_AST_EXPR_MEMBER:
case SCC_AST_EXPR_PTR_MEMBER:
dump_child_node((scc_ast_node_t *)expr->member.base, ctx, false);
// 打印成员访问信息
scc_tree_print_indent(ctx);
PRINT_NODE(ctx, "Member [\"%s\"]", expr->member.member_name);
scc_printf("\n");
break;
case SCC_AST_EXPR_CAST:
dump_child_node((scc_ast_node_t *)expr->cast.type, ctx, false);
dump_child_node((scc_ast_node_t *)expr->cast.expr, ctx, true);
break;
case SCC_AST_EXPR_SIZE_OF:
case SCC_AST_EXPR_ALIGN_OF:
if (expr->attr_of.expr) {
dump_child_node((scc_ast_node_t *)expr->attr_of.expr, ctx, true);
} else if (expr->attr_of.type) {
dump_child_node((scc_ast_node_t *)expr->attr_of.type, ctx, true);
}
break;
case SCC_AST_EXPR_COMPOUND_LITERAL:
dump_child_node((scc_ast_node_t *)expr->compound_literal.type, ctx,
false);
// 初始化列表
for (size_t i = 0; i < expr->compound_literal.init_list.size; i++) {
dump_child_node(
(scc_ast_node_t *)expr->compound_literal.init_list.data[i], ctx,
i == expr->compound_literal.init_list.size - 1);
}
break;
default:
break;
}
}
// 递归转储语句
static void dump_stmt_impl(scc_ast_stmt_t *stmt, scc_tree_dump_ctx_t *ctx) {
if (!stmt)
return;
start_node_dump(&stmt->base, ctx);
// 根据语句类型输出特定信息
switch (stmt->base.type) {
case SCC_AST_STMT_IF:
end_node_dump(ctx);
dump_child_node((scc_ast_node_t *)stmt->if_stmt.cond, ctx, false);
dump_child_node((scc_ast_node_t *)stmt->if_stmt.then_stmt, ctx,
!stmt->if_stmt.opt_else_stmt);
if (stmt->if_stmt.opt_else_stmt) {
dump_child_node((scc_ast_node_t *)stmt->if_stmt.opt_else_stmt, ctx,
true);
}
return;
case SCC_AST_STMT_WHILE:
end_node_dump(ctx);
dump_child_node((scc_ast_node_t *)stmt->while_stmt.cond, ctx, false);
dump_child_node((scc_ast_node_t *)stmt->while_stmt.body, ctx, true);
return;
case SCC_AST_STMT_DO_WHILE:
end_node_dump(ctx);
dump_child_node((scc_ast_node_t *)stmt->do_while_stmt.body, ctx, false);
dump_child_node((scc_ast_node_t *)stmt->do_while_stmt.cond, ctx, true);
return;
case SCC_AST_STMT_SWITCH:
end_node_dump(ctx);
dump_child_node((scc_ast_node_t *)stmt->switch_stmt.cond, ctx, false);
dump_child_node((scc_ast_node_t *)stmt->switch_stmt.body, ctx, true);
return;
case SCC_AST_STMT_FOR:
end_node_dump(ctx);
if (stmt->for_stmt.init) {
dump_child_node((scc_ast_node_t *)stmt->for_stmt.init, ctx, false);
}
if (stmt->for_stmt.cond) {
dump_child_node((scc_ast_node_t *)stmt->for_stmt.cond, ctx, false);
}
if (stmt->for_stmt.iter) {
dump_child_node((scc_ast_node_t *)stmt->for_stmt.iter, ctx, false);
}
dump_child_node((scc_ast_node_t *)stmt->for_stmt.body, ctx, true);
return;
case SCC_AST_STMT_RETURN:
if (stmt->return_stmt.expr) {
end_node_dump(ctx);
dump_child_node((scc_ast_node_t *)stmt->return_stmt.expr, ctx,
true);
} else {
end_node_dump(ctx);
}
break;
case SCC_AST_STMT_GOTO:
if (stmt->goto_stmt.label) {
PRINT_VALUE(ctx, " Label: %s", stmt->goto_stmt.label);
}
end_node_dump(ctx);
break;
case SCC_AST_STMT_LABEL:
if (stmt->label_stmt.label) {
PRINT_VALUE(ctx, " %s", stmt->label_stmt.label);
}
end_node_dump(ctx);
break;
case SCC_AST_STMT_COMPOUND:
end_node_dump(ctx);
for (size_t i = 0; i < stmt->compound.block_items.size; i++) {
scc_ast_node_t *item =
(scc_ast_node_t *)stmt->compound.block_items.data[i];
dump_child_node(item, ctx,
i == stmt->compound.block_items.size - 1);
}
break;
case SCC_AST_STMT_EXPR:
end_node_dump(ctx);
if (stmt->expr.expr) {
dump_child_node((scc_ast_node_t *)stmt->expr.expr, ctx, true);
}
break;
case SCC_AST_STMT_CASE:
end_node_dump(ctx);
dump_child_node((scc_ast_node_t *)stmt->case_stmt.expr, ctx, false);
dump_child_node((scc_ast_node_t *)stmt->case_stmt.stmt, ctx, true);
break;
case SCC_AST_STMT_DEFAULT:
end_node_dump(ctx);
dump_child_node((scc_ast_node_t *)stmt->default_stmt.stmt, ctx, true);
break;
default:
LOG_WARN("unknown node type %d", stmt->base.type);
break;
}
}
// 递归转储声明
static void dump_decl_impl(scc_ast_decl_t *decl, scc_tree_dump_ctx_t *ctx) {
if (!decl)
return;
start_node_dump(&decl->base, ctx);
// 根据声明类型输出特定信息
switch (decl->base.type) {
case SCC_AST_DECL_VAR:
if (decl->var.name) {
PRINT_QUOTED_VALUE(ctx, decl->var.name);
}
break;
case SCC_AST_DECL_FUNC:
if (decl->func.name) {
PRINT_QUOTED_VALUE(ctx, decl->func.name);
}
break;
case SCC_AST_DECL_PARAM:
if (decl->param.name) {
PRINT_QUOTED_VALUE(ctx, decl->param.name);
}
break;
case SCC_AST_DECL_STRUCT:
if (decl->record.name) {
PRINT_QUOTED_VALUE(ctx, decl->record.name);
}
break;
case SCC_AST_DECL_UNION:
if (decl->record.name) {
PRINT_QUOTED_VALUE(ctx, decl->record.name);
}
break;
case SCC_AST_DECL_ENUM:
if (decl->enumeration.name) {
PRINT_QUOTED_VALUE(ctx, decl->enumeration.name);
}
break;
case SCC_AST_DECL_TYPEDEF:
if (decl->typedef_decl.name) {
PRINT_QUOTED_VALUE(ctx, decl->typedef_decl.name);
}
break;
default:
break;
}
end_node_dump(ctx);
// 递归转储子节点
switch (decl->base.type) {
case SCC_AST_DECL_VAR:
if (decl->var.type) {
dump_child_node((scc_ast_node_t *)decl->var.type, ctx,
decl->var.init == NULL);
if (decl->var.init) {
dump_child_node((scc_ast_node_t *)decl->var.init, ctx, true);
}
}
break;
case SCC_AST_DECL_FUNC:
if (decl->func.type) {
dump_child_node((scc_ast_node_t *)decl->func.type, ctx,
decl->func.body == NULL);
if (decl->func.body) {
dump_child_node((scc_ast_node_t *)decl->func.body, ctx, true);
}
}
break;
case SCC_AST_DECL_PARAM:
if (decl->param.type) {
dump_child_node((scc_ast_node_t *)decl->param.type, ctx, true);
}
break;
case SCC_AST_DECL_STRUCT:
case SCC_AST_DECL_UNION:
for (size_t i = 0; i < decl->record.fields.size; i++) {
dump_child_node((scc_ast_node_t *)decl->record.fields.data[i], ctx,
i == decl->record.fields.size - 1);
}
break;
case SCC_AST_DECL_ENUM:
for (size_t i = 0; i < decl->enumeration.enumerators.size; i++) {
dump_child_node(
(scc_ast_node_t *)decl->enumeration.enumerators.data[i], ctx,
i == decl->enumeration.enumerators.size - 1);
}
break;
case SCC_AST_DECL_TYPEDEF:
if (decl->typedef_decl.type) {
dump_child_node((scc_ast_node_t *)decl->typedef_decl.type, ctx,
true);
}
break;
default:
break;
}
}
// 递归转储翻译单元
static void dump_unit_impl(scc_ast_translation_unit_t *unit,
scc_tree_dump_ctx_t *ctx) {
if (!unit)
return;
start_node_dump(&unit->base, ctx);
end_node_dump(ctx);
for (size_t i = 0; i < unit->declarations.size; i++) {
dump_child_node((scc_ast_node_t *)unit->declarations.data[i], ctx,
i == unit->declarations.size - 1);
}
}
void scc_ast_dump_node(scc_tree_dump_ctx_t *ctx, const scc_ast_node_t *node) {
if (!node)
return;
if (SCC_AST_IS_A(scc_ast_expr_t, node)) {
dump_expr_impl(SCC_AST_CAST_TO(scc_ast_expr_t, node), ctx);
} else if (SCC_AST_IS_A(scc_ast_stmt_t, node)) {
dump_stmt_impl(SCC_AST_CAST_TO(scc_ast_stmt_t, node), ctx);
} else if (SCC_AST_IS_A(scc_ast_decl_t, node)) {
dump_decl_impl(SCC_AST_CAST_TO(scc_ast_decl_t, node), ctx);
} else if (SCC_AST_IS_A(scc_ast_type_t, node)) {
dump_type_impl(SCC_AST_CAST_TO(scc_ast_type_t, node), ctx);
} else if (SCC_AST_IS_A(scc_ast_translation_unit_t, node)) {
dump_unit_impl(SCC_AST_CAST_TO(scc_ast_translation_unit_t, node), ctx);
}
}

View File

@@ -0,0 +1,10 @@
#include <stdio.h>
void test_example() {
printf("Test passed!\n");
}
int main() {
test_example();
return 0;
}

9
libs/ast2ir/cbuild.toml Normal file
View File

@@ -0,0 +1,9 @@
[package]
name = ""
version = "0.1.0"
authors = []
description = ""
# dependencies = []
# features = {}
# default_features = []

View File

@@ -0,0 +1,10 @@
#ifndef __SCC_AST2IR_H__
#define __SCC_AST2IR_H__
#include <lexer_token.h>
#include <scc_ast.h>
#include <scc_ir.h>
void scc_ast2ir(scc_ast_translation_unit_t *tu, scc_ir_builder_t *builder);
#endif /* __SCC_AST2IR_H__ */

553
libs/ast2ir/src/ast2ir.c Normal file
View File

@@ -0,0 +1,553 @@
#include <ir_builtin.h>
#include <scc_ast2ir.h>
static scc_ir_node_ref_t ast_expr_to_ir(scc_ir_builder_t *ctx,
scc_ast_expr_t *expr);
static void ast_stmt_to_ir(scc_ir_builder_t *ctx, scc_ast_stmt_t *stmt);
static void ast_decl_to_ir(scc_ir_builder_t *ctx, scc_ast_decl_t *decl);
static scc_ir_type_ref_t ast_type_to_ir_type(scc_ir_builder_t *ctx,
scc_ast_type_t *ast_type);
// 转换AST类型为IR类型
static scc_ir_type_ref_t ast_type_to_ir_type(scc_ir_builder_t *ctx,
scc_ast_type_t *ast_type) {
if (ctx == null || ast_type == null) {
LOG_ERROR("args is null");
return 0;
}
scc_ir_type_t ir_type;
switch (ast_type->base.type) {
case SCC_AST_TYPE_BUILTIN: {
// 映射内置类型
scc_ir_type_init(&ir_type, SCC_IR_TYPE_I32);
// TODO: 根据具体内置类型设置
break;
}
case SCC_AST_TYPE_POINTER: {
scc_ir_type_init(&ir_type, SCC_IR_TYPE_PTR);
// 创建指向类型并添加到程序类型列表
scc_ir_type_ref_t pointee_type =
ast_type_to_ir_type(ctx, ast_type->pointer.pointee);
// 注意:我们需要找到一种合适的方式来存储类型信息
// 目前的IR设计中类型信息应该直接存储在类型结构中
ir_type.data.pointer.base = pointee_type;
break;
}
case SCC_AST_TYPE_ARRAY: {
scc_ir_type_init(&ir_type, SCC_IR_TYPE_ARRAY);
// 创建元素类型并添加到程序类型列表
scc_ir_type_ref_t element_type =
ast_type_to_ir_type(ctx, ast_type->array.element);
// 将类型添加到程序的类型容器中
ir_type.data.array.base = element_type;
// TODO: 处理数组大小表达式
ir_type.data.array.len = 0; // 暂时设为0
break;
}
case SCC_AST_TYPE_FUNCTION: {
scc_ir_type_init(&ir_type, SCC_IR_TYPE_FUNC);
// 处理返回类型
scc_ir_type_ref_t ret_type =
ast_type_to_ir_type(ctx, ast_type->function.return_type);
// 将返回类型添加到程序的类型容器中
ir_type.data.function.ret_type = ret_type;
// 转换参数类型
scc_ir_type_ref_vec_t params;
scc_vec_init(params);
scc_vec_foreach(ast_type->function.param_types, i) {
scc_ast_type_t *param_type =
scc_vec_at(ast_type->function.param_types, i);
scc_ir_type_ref_t tmp_type = ast_type_to_ir_type(ctx, param_type);
scc_vec_push(params, tmp_type);
}
ir_type.data.function.params = params;
break;
}
default:
LOG_FATAL("Unsupported AST type: %d", ast_type->base.type);
return 0;
}
return scc_ir_ctx_new_type(&ctx->ctx, &ir_type);
}
// 转换AST表达式为IR节点
static scc_ir_node_ref_t ast_expr_to_ir(scc_ir_builder_t *ctx,
scc_ast_expr_t *expr) {
if (ctx == null || expr == null) {
LOG_ERROR("args is null");
return 0;
}
switch (expr->base.type) {
case SCC_AST_EXPR_IDENTIFIER: {
// TODO maybe error or need symtab
scc_ir_node_t in;
scc_ir_node_init(&in, expr->identifier.name, SCC_IR_NODE_LOAD);
return scc_ir_ctx_new_node(&ctx->ctx, &in);
}
case SCC_AST_EXPR_INT_LITERAL: {
return scc_ir_ctx_get_i32_const(&ctx->ctx, expr->literal.value.i);
}
case SCC_AST_EXPR_BINARY: {
// 转换左右操作数
scc_ir_node_ref_t lhs, rhs;
lhs = ast_expr_to_ir(ctx, expr->binary.lhs);
rhs = ast_expr_to_ir(ctx, expr->binary.rhs);
// 映射操作符
scc_ir_op_type_t op;
switch (expr->binary.op) {
/* clang-format off */
case SCC_AST_OP_ADD: op = IR_OP_ADD; break;
case SCC_AST_OP_SUB: op = IR_OP_SUB; break;
case SCC_AST_OP_MUL: op = IR_OP_MUL; break;
case SCC_AST_OP_DIV: op = IR_OP_DIV; break;
case SCC_AST_OP_MOD: op = IR_OP_MOD; break;
case SCC_AST_OP_LOGICAL_AND: op = IR_OP_AND; break;
case SCC_AST_OP_LOGICAL_OR: op = IR_OP_OR; break;
case SCC_AST_OP_BITWISE_XOR: op = IR_OP_XOR; break;
case SCC_AST_OP_LEFT_SHIFT: op = IR_OP_SHL; break;
case SCC_AST_OP_RIGHT_SHIFT: op = IR_OP_SHR; break;
case SCC_AST_OP_EQUAL: op = IR_OP_EQ; break;
case SCC_AST_OP_NOT_EQUAL: op = IR_OP_NEQ; break;
case SCC_AST_OP_LESS: op = IR_OP_LT; break;
case SCC_AST_OP_LESS_EQUAL: op = IR_OP_LE; break;
case SCC_AST_OP_GREATER: op = IR_OP_GT; break;
case SCC_AST_OP_GREATER_EQUAL: op = IR_OP_GE; break;
case SCC_AST_OP_ASSIGN: {
// 赋值表达式:存储右值到左值位置
return scc_ir_builder_store(ctx, lhs, rhs);
}
case SCC_AST_OP_ASSIGN_ADD:
TODO();
/* clang-format on */
default:
LOG_WARN("Unsupported binary operator: %d", expr->binary.op);
op = IR_OP_ADD; // 默认
}
// 创建操作节点
return scc_ir_builder_binop(ctx, op, lhs, rhs);
}
case SCC_AST_EXPR_UNARY: {
// 转换操作数
scc_ir_node_ref_t operand = ast_expr_to_ir(ctx, expr->unary.operand);
// 映射一元操作符
switch (expr->unary.op) {
case SCC_TOK_SUB:
// 负号
// 实现为0 - operand
return scc_ir_builder_binop(ctx, IR_OP_SUB,
scc_ir_ctx_get_builtin_zero(&ctx->ctx),
operand);
case SCC_TOK_BIT_NOT:
// 按位取反
return scc_ir_builder_binop(ctx, IR_OP_NOT, operand, 0);
case SCC_TOK_NOT:
// 逻辑非
// 实现为与0比较
return scc_ir_builder_binop(
ctx, IR_OP_EQ, scc_ir_ctx_get_builtin_zero(&ctx->ctx), operand);
default:
LOG_WARN("Unsupported unary operator: %d", expr->unary.op);
return 0;
}
}
case SCC_AST_EXPR_COND: {
TODO();
break;
}
case SCC_AST_EXPR_CALL: {
// 转换参数
scc_ir_node_ref_vec_t args;
scc_vec_init(args);
// 检查参数是否为空
if (expr->call.args.data != null) {
scc_vec_foreach(expr->call.args, i) {
scc_ast_expr_t *arg_expr = scc_vec_at(expr->call.args, i);
scc_ir_node_ref_t arg_node;
arg_node = ast_expr_to_ir(ctx, arg_expr);
scc_vec_push(args, arg_node);
}
}
// 创建调用节点(需要查找函数定义)
// TODO: 需要符号表查找函数
scc_ir_node_ref_t func =
scc_ir_builder_call(ctx, 0, args.data, args.size);
scc_vec_free(args);
return func;
}
default:
LOG_WARN("Unsupported expression type: %d", expr->base.type);
return 0;
}
}
// 转换AST语句为IR
static void ast_stmt_to_ir(scc_ir_builder_t *ctx, scc_ast_stmt_t *stmt) {
if (stmt == null) {
return;
}
switch (stmt->base.type) {
case SCC_AST_STMT_COMPOUND: {
// 进入新的作用域
scc_vec_foreach(stmt->compound.block_items, i) {
scc_ast_node_t *child_stmt =
scc_vec_at(stmt->compound.block_items, i);
if (SCC_AST_IS_A(scc_ast_stmt_t, child_stmt)) {
ast_stmt_to_ir(ctx,
SCC_AST_CAST_TO(scc_ast_stmt_t, child_stmt));
} else if (SCC_AST_IS_A(scc_ast_decl_t, child_stmt)) {
ast_decl_to_ir(ctx,
SCC_AST_CAST_TO(scc_ast_decl_t, child_stmt));
} else {
UNREACHABLE();
}
}
break;
}
case SCC_AST_STMT_EXPR: {
ast_expr_to_ir(ctx, stmt->expr.expr);
break;
}
// case SCC_AST_STMT_IF: {
// // 创建基本块 - 统一使用栈上分配
// scc_ir_bblock_t true_block;
// scc_ir_bblock_init(&true_block, "if_true");
// scc_ir_bblock_t false_block;
// scc_ir_bblock_init(&false_block, "if_false");
// scc_ir_bblock_t merge_block;
// scc_ir_bblock_init(&merge_block, "if_merge");
// // 转换条件
// scc_ir_node_ref_t cond_node = ast_expr_to_ir(ctx,
// stmt->if_stmt.cond);
// // 创建分支指令
// scc_ir_builder_branch();
// scc_ir_node_t br_node;
// init_branch_node(&br_node, cond, &true_block, &false_block);
// emit_instruction(ctx, &br_node);
// // 保存当前块
// ast2ir_ctx_t saved = ctx->current_ctx;
// // 生成true分支
// emit_basicblock(ctx, &true_block);
// ast_stmt_to_ir(ctx, stmt->if_stmt.then_stmt);
// // 跳转到合并块
// scc_ir_node_t jump_node;
// init_jump_node(&jump_node, &merge_block);
// emit_instruction(ctx, &jump_node);
// // 生成false分支如果有
// emit_basicblock(ctx, &false_block);
// if (stmt->if_stmt.opt_else_stmt) {
// ast_stmt_to_ir(ctx, stmt->if_stmt.opt_else_stmt);
// }
// // 跳转到合并块
// init_jump_node(&jump_node, &merge_block);
// emit_instruction(ctx, &jump_node);
// // 恢复上下文并设置当前块为合并块
// ctx->current_ctx = saved;
// emit_basicblock(ctx, &merge_block);
// break;
// }
// case SCC_AST_STMT_WHILE: {
// // 创建基本块 - 统一使用栈上分配
// scc_ir_bblock_t cond_block;
// scc_ir_bblock_init(&cond_block, "while_cond");
// scc_ir_bblock_t body_block;
// scc_ir_bblock_init(&body_block, "while_body");
// scc_ir_bblock_t exit_block;
// scc_ir_bblock_init(&exit_block, "while_exit");
// // 跳转到条件块
// scc_ir_node_t jump_node;
// init_jump_node(&jump_node, &cond_block);
// emit_instruction(ctx, &jump_node);
// // 保存当前块
// ast2ir_ctx_t saved = ctx->current_ctx;
// // 生成条件块
// emit_basicblock(ctx, &cond_block);
// scc_ir_node_t cond_node;
// ast_expr_to_ir(ctx, stmt->while_stmt.cond, &cond_node);
// // 将条件节点添加到程序节点列表
// scc_vec_push(ctx->program->global_vals, cond_node);
// scc_ir_node_t *cond =
// &scc_vec_at(ctx->program->global_vals,
// scc_vec_size(ctx->program->global_vals) - 1);
// // 创建分支
// scc_ir_node_t br_node;
// init_branch_node(&br_node, cond, &body_block, &exit_block);
// emit_instruction(ctx, &br_node);
// // 生成循环体
// emit_basicblock(ctx, &body_block);
// ast_stmt_to_ir(ctx, stmt->while_stmt.body);
// // 跳转回条件块
// init_jump_node(&jump_node, &cond_block);
// emit_instruction(ctx, &jump_node);
// // 恢复上下文并设置当前块为退出块
// ctx->current_ctx = saved;
// emit_basicblock(ctx, &exit_block);
// break;
// }
// case SCC_AST_STMT_DO_WHILE: {
// // 创建基本块 - 统一使用栈上分配
// scc_ir_bblock_t cond_block;
// scc_ir_bblock_init(&cond_block, "do_while_cond");
// scc_ir_bblock_t body_block;
// scc_ir_bblock_init(&body_block, "do_while_body");
// scc_ir_bblock_t exit_block;
// scc_ir_bblock_init(&exit_block, "do_while_exit");
// // 跳转到循环体块
// scc_ir_node_t jump_node;
// init_jump_node(&jump_node, &body_block);
// emit_instruction(ctx, &jump_node);
// // 保存当前块
// ast2ir_ctx_t saved = ctx->current_ctx;
// // 生成循环体
// emit_basicblock(ctx, &body_block);
// ast_stmt_to_ir(ctx, stmt->do_while_stmt.body);
// // 跳转到条件块
// init_jump_node(&jump_node, &cond_block);
// emit_instruction(ctx, &jump_node);
// // 生成条件块
// emit_basicblock(ctx, &cond_block);
// scc_ir_node_t cond_node;
// ast_expr_to_ir(ctx, stmt->do_while_stmt.cond, &cond_node);
// // 将条件节点添加到程序节点列表
// scc_vec_push(ctx->program->global_vals, cond_node);
// scc_ir_node_t *cond =
// &scc_vec_at(ctx->program->global_vals,
// scc_vec_size(ctx->program->global_vals) - 1);
// // 创建分支
// scc_ir_node_t br_node;
// init_branch_node(&br_node, cond, &body_block, &exit_block);
// emit_instruction(ctx, &br_node);
// // 恢复上下文并设置当前块为退出块
// ctx->current_ctx = saved;
// emit_basicblock(ctx, &exit_block);
// break;
// }
// case SCC_AST_STMT_FOR: {
// // 初始化部分
// if (SCC_AST_IS_A(scc_ast_expr_t, stmt->for_stmt.init)) {
// scc_ir_node_t dummy_node;
// ast_expr_to_ir(ctx,
// SCC_AST_CAST_TO(scc_ast_expr_t,
// stmt->for_stmt.init), &dummy_node);
// } else if (SCC_AST_IS_A(scc_ast_decl_t, stmt->for_stmt.init)) {
// ast_decl_to_ir(
// ctx, SCC_AST_CAST_TO(scc_ast_decl_t,
// stmt->for_stmt.init));
// } else {
// UNREACHABLE();
// }
// // 创建基本块 - 统一使用栈上分配
// scc_ir_bblock_t cond_block;
// scc_ir_bblock_init(&cond_block, "for_cond");
// scc_ir_bblock_t body_block;
// scc_ir_bblock_init(&body_block, "for_body");
// scc_ir_bblock_t exit_block;
// scc_ir_bblock_init(&exit_block, "for_exit");
// // 跳转到条件块
// scc_ir_node_t jump_node;
// init_jump_node(&jump_node, &cond_block);
// emit_instruction(ctx, &jump_node);
// // 保存当前块
// ast2ir_ctx_t saved = ctx->current_ctx;
// // 生成条件块
// emit_basicblock(ctx, &cond_block);
// scc_ir_node_t *cond = null;
// if (stmt->for_stmt.cond) {
// scc_ir_node_t cond_node;
// ast_expr_to_ir(ctx, stmt->for_stmt.cond, &cond_node);
// // 将条件节点添加到程序节点列表
// scc_vec_push(ctx->program->global_vals, cond_node);
// cond = &scc_vec_at(ctx->program->global_vals,
// scc_vec_size(ctx->program->global_vals) -
// 1);
// } else {
// // 无条件循环,条件为真
// scc_ir_node_t true_node;
// init_const_int_node(&true_node, 1, null);
// // 将true节点添加到程序节点列表
// scc_vec_push(ctx->program->global_vals, true_node);
// cond = &scc_vec_at(ctx->program->global_vals,
// scc_vec_size(ctx->program->global_vals) -
// 1);
// }
// // 创建分支
// scc_ir_node_t br_node;
// init_branch_node(&br_node, cond, &body_block, &exit_block);
// emit_instruction(ctx, &br_node);
// // 生成循环体
// emit_basicblock(ctx, &body_block);
// ast_stmt_to_ir(ctx, stmt->for_stmt.body);
// // 执行迭代表达式(如果存在)
// if (stmt->for_stmt.iter) {
// scc_ir_node_t dummy_node;
// ast_expr_to_ir(ctx, stmt->for_stmt.iter, &dummy_node);
// }
// // 跳转回条件块
// init_jump_node(&jump_node, &cond_block);
// emit_instruction(ctx, &jump_node);
// // 恢复上下文并设置当前块为退出块
// ctx->current_ctx = saved;
// emit_basicblock(ctx, &exit_block);
// break;
// }
case SCC_AST_STMT_RETURN: {
if (stmt->return_stmt.expr) {
scc_ir_node_ref_t ret_val_node =
ast_expr_to_ir(ctx, stmt->return_stmt.expr);
scc_ir_builder_ret(ctx, ret_val_node);
} else {
scc_ir_builder_ret_void(ctx);
}
break;
}
default:
LOG_WARN("Unsupported statement type: %d", stmt->base.type);
break;
}
}
// 转换AST声明为IR
static void ast_decl_to_ir(scc_ir_builder_t *ctx, scc_ast_decl_t *decl) {
if (ctx == null || decl == null) {
LOG_ERROR("Invalid argument");
return;
}
switch (decl->base.type) {
case SCC_AST_DECL_VAR: {
// 转换类型
scc_ir_type_ref_t ir_type = ast_type_to_ir_type(ctx, decl->var.type);
// 创建分配节点
scc_ir_node_ref_t alloc_val_node =
scc_ir_builder_alloca(ctx, ir_type, decl->var.name);
// 如果有初始化表达式
if (!decl->var.init) {
break;
}
scc_ir_node_ref_t init_val_node = ast_expr_to_ir(ctx, decl->var.init);
// 将初始化值节点添加到程序节点列表
// scc_vec_push(ctx->program->global_vals, init_val_node);
// scc_ir_node_t *init_val =
// &scc_vec_at(ctx->program->global_vals,
// scc_vec_size(ctx->program->global_vals) - 1);
scc_ir_builder_store(ctx, alloc_val_node, init_val_node);
break;
}
case SCC_AST_DECL_FUNC: {
// TODO params name
scc_ir_type_ref_t func_type = ast_type_to_ir_type(ctx, decl->func.type);
scc_ir_builder_begin_func(ctx, decl->func.name, func_type, null);
// 处理函数体(如果有)
if (decl->func.body) {
scc_ir_builder_begin_bblock(ctx, "entry");
ast_stmt_to_ir(ctx, decl->func.body);
scc_ir_builder_end_bblock(ctx);
}
scc_ir_builder_end_func(ctx);
break;
}
default:
LOG_WARN("Unsupported declaration type: %d", decl->base.type);
break;
}
}
// 主转换函数将AST翻译单元转换为IR程序
void scc_ast2ir(scc_ast_translation_unit_t *tu, scc_ir_builder_t *builder) {
if (tu == null || builder == null) {
LOG_ERROR("Invalid argument");
return;
}
// 初始化上下文
scc_ir_builder_init(builder);
// 转换所有声明
scc_vec_foreach(tu->declarations, i) {
scc_ast_decl_t *decl = scc_vec_at(tu->declarations, i);
ast_decl_to_ir(builder, decl);
}
}

10
libs/ast2ir/tests/test_.c Normal file
View File

@@ -0,0 +1,10 @@
#include <stdio.h>
void test_example() {
printf("Test passed!\n");
}
int main() {
test_example();
return 0;
}

View File

@@ -4,7 +4,10 @@ version = "0.1.0"
authors = []
description = ""
dependencies = [{ name = "scc_core", path = "../../runtime/scc_core" }]
dependencies = [
{ name = "scc_utils", path = "../../runtime/scc_utils" },
{ name = "tree_dump", path = "../tree_dump" },
]
# dependencies = []
# features = {}
# default_features = []

17
libs/ir/include/ir_base.h Normal file
View File

@@ -0,0 +1,17 @@
#ifndef __SCC_IR_BASE_H__
#define __SCC_IR_BASE_H__
#include "ir_def.h"
void scc_ir_type_init(scc_ir_type_t *in, scc_ir_type_tag_t tag);
void scc_ir_bblock_init(scc_ir_bblock_t *in, const char *label);
void scc_ir_func_init(scc_ir_func_t *in, const char *name);
// node name can be null ptr
void scc_ir_node_init(scc_ir_node_t *in, const char *name,
scc_ir_node_tag_t tag);
void scc_ir_cprog_init(scc_ir_cprog_t *in);
void scc_ir_cprog_drop(scc_ir_cprog_t *in);
#endif /* __SCC_IR_BASE_H__ */

View File

@@ -0,0 +1,174 @@
#ifndef __SCC_IR_BUILDER_H__
#define __SCC_IR_BUILDER_H__
#include "ir_ctx.h"
#include "ir_def.h"
#include <scc_core.h>
typedef struct scc_ir_builder scc_ir_builder_t;
/**
* @brief IR 构建器上下文
*
* 负责管理 IR 构建过程中的所有状态:
* - 类型统一化type uniquing
* - 符号命名分配
* - 内存管理
* - 当前构建位置(函数、基本块)
*/
struct scc_ir_builder {
scc_ir_cprog_ctx_t ctx; /**< 核心上下文 */
scc_ir_cprog_t cprog;
// 当前构建位置
scc_ir_func_ref_t current_func; /**< 当前正在构建的函数 */
scc_ir_bblock_ref_t current_bblock; /**< 当前基本块 */
};
/**
* @brief 初始化 IR 构建器
*/
void scc_ir_builder_init(scc_ir_builder_t *builder);
/**
* @brief 销毁 IR 构建器及其所有资源
*/
void scc_ir_builder_drop(scc_ir_builder_t *builder);
/**
* @brief 开始构建函数
* @param name 函数名
* @param type 函数类型
* @param param_names 参数名列表可为NULL
* @return 函数引用
*/
scc_ir_func_ref_t scc_ir_builder_begin_func(scc_ir_builder_t *builder,
const char *name,
scc_ir_type_ref_t type,
const char **param_names);
/**
* @brief 结束当前函数的构建
*/
void scc_ir_builder_end_func(scc_ir_builder_t *builder);
/**
* @brief 获取当前正在构建的函数
*/
scc_ir_func_ref_t scc_ir_builder_current_func(scc_ir_builder_t *builder);
/**
* @brief 开始构建新的基本块
* @param label 基本块标签可为NULL自动生成
* @return 基本块引用
*/
scc_ir_bblock_ref_t scc_ir_builder_begin_bblock(scc_ir_builder_t *builder,
const char *label);
/**
* @brief 结束当前基本块的构建
*/
void scc_ir_builder_end_bblock(scc_ir_builder_t *builder);
/**
* @brief 设置当前基本块
*/
void scc_ir_builder_set_current_bblock(scc_ir_builder_t *builder,
scc_ir_bblock_ref_t bblock);
/**
* @brief 创建alloca指令在当前基本块中
* @param type 分配的类型
* @param name 变量名可为NULL
*/
scc_ir_node_ref_t scc_ir_builder_alloca(scc_ir_builder_t *builder,
scc_ir_type_ref_t type,
const char *name);
/**
* @brief 创建load指令
* @param ptr 指针操作数
*/
scc_ir_node_ref_t scc_ir_builder_load(scc_ir_builder_t *builder,
scc_ir_node_ref_t ptr);
/**
* @brief 创建store指令
* @param ptr 目标指针
* @param value 要存储的值
*/
scc_ir_node_ref_t scc_ir_builder_store(scc_ir_builder_t *builder,
scc_ir_node_ref_t ptr,
scc_ir_node_ref_t value);
/**
* @brief 创建getptr指令指针运算
* @param ptr 基础指针
* @param index 索引值
*/
scc_ir_node_ref_t scc_ir_builder_get_ptr(scc_ir_builder_t *builder,
scc_ir_node_ref_t ptr,
scc_ir_node_ref_t index);
/**
* @brief 创建二元运算指令
* @param op 操作符
* @param lhs 左操作数
* @param rhs 右操作数
*/
scc_ir_node_ref_t scc_ir_builder_binop(scc_ir_builder_t *builder,
scc_ir_op_type_t op,
scc_ir_node_ref_t lhs,
scc_ir_node_ref_t rhs);
/**
* @brief 创建比较指令
* @param op 比较操作符
* @param lhs 左操作数
* @param rhs 右操作数
*/
scc_ir_node_ref_t scc_ir_builder_cmp(scc_ir_builder_t *builder,
scc_ir_op_type_t op, scc_ir_node_ref_t lhs,
scc_ir_node_ref_t rhs);
/**
* @brief 创建跳转指令(无条件)
* @param target 目标基本块
*/
scc_ir_node_ref_t scc_ir_builder_jump(scc_ir_builder_t *builder,
scc_ir_bblock_ref_t target);
/**
* @brief 创建条件分支指令
* @param cond 条件值
* @param true_target 条件为真时的目标
* @param false_target 条件为假时的目标
*/
scc_ir_node_ref_t scc_ir_builder_branch(scc_ir_builder_t *builder,
scc_ir_node_ref_t cond,
scc_ir_bblock_ref_t true_target,
scc_ir_bblock_ref_t false_target);
/**
* @brief 创建函数调用指令
* @param callee 被调用函数
* @param args 参数列表
* @param arg_count 参数数量
*/
scc_ir_node_ref_t scc_ir_builder_call(scc_ir_builder_t *builder,
scc_ir_func_ref_t callee,
const scc_ir_node_ref_t *args,
usize arg_count);
/**
* @brief 创建返回指令(带返回值)
* @param value 返回值
*/
scc_ir_node_ref_t scc_ir_builder_ret(scc_ir_builder_t *builder,
scc_ir_node_ref_t value);
/**
* @brief 创建返回指令void返回
*/
scc_ir_node_ref_t scc_ir_builder_ret_void(scc_ir_builder_t *builder);
#endif /* __SCC_IR_BUILDER_H__ */

200
libs/ir/include/ir_ctx.h Normal file
View File

@@ -0,0 +1,200 @@
#ifndef __SCC_IR_CTX_H__
#define __SCC_IR_CTX_H__
#include "ir_base.h"
#include "ir_def.h"
#include <scc_hashtable.h>
#define SCC_IR_REF_NULL 0
typedef struct {
unsigned int node_uid;
unsigned int type_uid;
unsigned int bblock_uid;
unsigned int func_uid;
SCC_VEC(scc_ir_node_t) nodes;
SCC_VEC(scc_ir_type_t) types;
SCC_VEC(scc_ir_bblock_t) bblocks;
SCC_VEC(scc_ir_func_t) funcs;
// UID -> 索引 映射
scc_hashtable_t uid2nodes;
scc_hashtable_t uid2types;
scc_hashtable_t uid2bblocks;
scc_hashtable_t uid2funcs;
// 类型去重表(类型键 -> 类型引用)
scc_hashtable_t type_uniquing;
// 常量池(常量键 -> 节点引用)
scc_hashtable_t const_pool;
// 内置类型缓存
scc_ir_type_ref_t builtin_i32;
scc_ir_type_ref_t builtin_i1;
scc_ir_type_ref_t builtin_void;
scc_ir_node_ref_t builtin_zero_i32;
} scc_ir_cprog_ctx_t;
/**
* @brief 初始化IR上下文
* @param ctx 上下文指针
*/
void scc_ir_ctx_init(scc_ir_cprog_ctx_t *ctx);
/**
* @brief 销毁IR上下文及其所有资源
* @param ctx 上下文指针
*/
void scc_ir_ctx_drop(scc_ir_cprog_ctx_t *ctx);
/**
* @brief 重置IR上下文清空所有数据但保留内存
* @param ctx 上下文指针
*/
void scc_ir_ctx_reset(scc_ir_cprog_ctx_t *ctx);
/**
* @brief 创建新的类型
* @param ctx 上下文指针
* @param type 类型数据(会被拷贝)
* @return 类型引用0表示失败
*/
scc_ir_type_ref_t scc_ir_ctx_new_type(scc_ir_cprog_ctx_t *ctx,
const scc_ir_type_t *type);
/**
* @brief 创建新的节点
* @param ctx 上下文指针
* @param node 节点数据(会被拷贝)
* @return 节点引用0表示失败
*/
scc_ir_node_ref_t scc_ir_ctx_new_node(scc_ir_cprog_ctx_t *ctx,
const scc_ir_node_t *node);
/**
* @brief 创建新的基本块
* @param ctx 上下文指针
* @param bblock 基本块数据(会被拷贝)
* @return 基本块引用0表示失败
*/
scc_ir_bblock_ref_t scc_ir_ctx_new_bblock(scc_ir_cprog_ctx_t *ctx,
const scc_ir_bblock_t *bblock);
/**
* @brief 创建新的函数
* @param ctx 上下文指针
* @param func 函数数据(会被拷贝)
* @return 函数引用0表示失败
*/
scc_ir_func_ref_t scc_ir_ctx_new_func(scc_ir_cprog_ctx_t *ctx,
const scc_ir_func_t *func);
/**
* @brief 根据引用获取类型
* @param ctx 上下文指针
* @param ref 类型引用
* @return 类型指针NULL表示无效引用
*/
scc_ir_type_t *scc_ir_ctx_get_type(scc_ir_cprog_ctx_t *ctx,
scc_ir_type_ref_t ref);
/**
* @brief 根据引用获取节点
* @param ctx 上下文指针
* @param ref 节点引用
* @return 节点指针NULL表示无效引用
*/
scc_ir_node_t *scc_ir_ctx_get_node(scc_ir_cprog_ctx_t *ctx,
scc_ir_node_ref_t ref);
/**
* @brief 根据引用获取基本块
* @param ctx 上下文指针
* @param ref 基本块引用
* @return 基本块指针NULL表示无效引用
*/
scc_ir_bblock_t *scc_ir_ctx_get_bblock(scc_ir_cprog_ctx_t *ctx,
scc_ir_bblock_ref_t ref);
/**
* @brief 根据引用获取函数
* @param ctx 上下文指针
* @param ref 函数引用
* @return 函数指针NULL表示无效引用
*/
scc_ir_func_t *scc_ir_ctx_get_func(scc_ir_cprog_ctx_t *ctx,
scc_ir_func_ref_t ref);
// /**
// * @brief 遍历所有类型
// * @param ctx 上下文指针
// * @param callback 回调函数
// * @param userdata 用户数据
// */
// void scc_ir_ctx_foreach_type(scc_ir_cprog_ctx_t *ctx,
// void (*callback)(scc_ir_type_ref_t ref,
// scc_ir_type_t *type,
// void *userdata),
// void *userdata);
// /**
// * @brief 遍历所有节点
// */
// void scc_ir_ctx_foreach_node(scc_ir_cprog_ctx_t *ctx,
// void (*callback)(scc_ir_node_ref_t ref,
// scc_ir_node_t *node,
// void *userdata),
// void *userdata);
// /**
// * @brief 遍历所有基本块
// */
// void scc_ir_ctx_foreach_bblock(scc_ir_cprog_ctx_t *ctx,
// void (*callback)(scc_ir_bblock_ref_t ref,
// scc_ir_bblock_t *bblock,
// void *userdata),
// void *userdata);
// /**
// * @brief 遍历所有函数
// */
// void scc_ir_ctx_foreach_func(scc_ir_cprog_ctx_t *ctx,
// void (*callback)(scc_ir_func_ref_t ref,
// scc_ir_func_t *func,
// void *userdata),
// void *userdata);
/**
* @brief 获取内置i32类型
* @param ctx 上下文指针
* @return i32类型引用
*/
scc_ir_type_ref_t scc_ir_ctx_get_builtin_i32(scc_ir_cprog_ctx_t *ctx);
/**
* @brief 获取内置零常量
* @param ctx 上下文指针
* @return 零常量节点引用
*/
scc_ir_node_ref_t scc_ir_ctx_get_builtin_zero(scc_ir_cprog_ctx_t *ctx);
/**
* @brief 创建或获取i32常量
* @param ctx 上下文指针
* @param value 常量值
* @return 常量节点引用
*/
scc_ir_node_ref_t scc_ir_ctx_get_i32_const(scc_ir_cprog_ctx_t *ctx, i32 value);
/**
* @brief 创建或获取null常量
* @param ctx 上下文指针
* @param ptr_type 指针类型引用
* @return null常量节点引用
*/
scc_ir_node_ref_t scc_ir_ctx_get_null_const(scc_ir_cprog_ctx_t *ctx,
scc_ir_type_ref_t ptr_type);
#endif /* __SCC_IR_CTX_H__ */

View File

@@ -3,52 +3,75 @@
#include <scc_core.h>
typedef unsigned int ir_handle_t;
typedef const char *scc_ir_label_t;
typedef struct scc_ir_node scc_ir_node_t;
typedef SCC_VEC(scc_ir_node_t) scc_ir_node_vec_t;
typedef ir_handle_t scc_ir_node_ref_t;
typedef SCC_VEC(scc_ir_node_ref_t) scc_ir_node_ref_vec_t;
typedef struct scc_ir_type scc_ir_type_t;
typedef ir_handle_t scc_ir_type_ref_t;
typedef SCC_VEC(scc_ir_type_ref_t) scc_ir_type_ref_vec_t;
typedef struct scc_ir_bblock scc_ir_bblock_t;
typedef ir_handle_t scc_ir_bblock_ref_t;
typedef SCC_VEC(scc_ir_bblock_ref_t) scc_ir_bblock_ref_vec_t;
typedef struct scc_ir_func scc_ir_func_t;
typedef ir_handle_t scc_ir_func_ref_t;
typedef SCC_VEC(scc_ir_func_ref_t) scc_ir_func_ref_vec_t;
typedef enum scc_ir_type_tag {
SCC_IR_TYPE_VOID,
SCC_IR_TYPE_I1,
SCC_IR_TYPE_I8,
SCC_IR_TYPE_I16,
SCC_IR_TYPE_I32,
SCC_IR_TYPE_I64,
SCC_IR_TYPE_I128,
SCC_IR_TYPE_F16,
SCC_IR_TYPE_F32,
SCC_IR_TYPE_F64,
SCC_IR_TYPE_F128,
SCC_IR_TYPE_PTR,
SCC_IR_TYPE_ARRAY,
SCC_IR_TYPE_FUNC,
SCC_IR_TYPE_STRUCT,
SCC_IR_TYPE_VECTOR,
} scc_ir_type_tag_t;
typedef struct scc_ir_type scc_ir_type_t;
typedef SCC_VEC(scc_ir_type_t) scc_ir_type_vec_t;
struct scc_ir_type {
scc_ir_type_tag_t tag;
// int size; // 字节大小
// int align; // 对齐要求
union {
struct {
const scc_ir_type_t *base;
usize len;
scc_ir_type_ref_t base;
usize len; // TODO usize is target dependent
} array;
struct {
const scc_ir_type_t *base;
scc_ir_type_ref_t base;
} pointer;
struct {
scc_ir_type_vec_t params;
const scc_ir_type_t *ret_type;
scc_ir_type_ref_vec_t params;
scc_ir_type_ref_t ret_type;
} function;
} data;
};
typedef struct scc_ir_bblock {
const char *label;
scc_ir_node_vec_t instrs;
struct scc_ir_bblock {
scc_ir_label_t label;
scc_ir_node_ref_vec_t instrs;
// ir_arr_t used_by;
} scc_ir_bblock_t; // basic block
typedef SCC_VEC(scc_ir_bblock_t) scc_ir_bblock_vec_t;
}; // basic block
typedef struct {
const char *name;
scc_ir_type_t *type;
scc_ir_node_vec_t params;
scc_ir_bblock_vec_t bblocks;
} scc_ir_func_t;
typedef SCC_VEC(scc_ir_func_t) scc_ir_func_vec_t;
struct scc_ir_func {
scc_ir_label_t name;
scc_ir_type_ref_t type;
scc_ir_node_ref_vec_t params;
scc_ir_bblock_ref_vec_t bblocks;
};
typedef enum scc_ir_node_tag {
SCC_IR_NODE_NULL,
@@ -106,9 +129,9 @@ typedef enum {
} scc_ir_op_type_t;
struct scc_ir_node {
const scc_ir_type_t *type;
const char *name;
scc_ir_node_vec_t used_by;
scc_ir_type_ref_t type;
scc_ir_label_t name;
scc_ir_node_ref_vec_t used_by;
scc_ir_node_tag_t tag;
union {
union {
@@ -117,7 +140,7 @@ struct scc_ir_node {
i32 int32;
i64 int64;
// TODO int128
i8 int_any[4];
i8 int_any[16];
} const_int;
union {
u8 uint8;
@@ -125,54 +148,54 @@ struct scc_ir_node {
u32 uint32;
u64 uint64;
// TODO uint128;
u8 uint_any[4];
u8 uint_any[16];
} const_uint;
// aggregate;
// func_arg_ref;
// block_arg_ref;
// global_alloc;
struct {
scc_ir_node_t *target;
scc_ir_node_ref_t target;
} load;
struct {
scc_ir_node_t *target;
scc_ir_node_t *value;
scc_ir_node_ref_t target;
scc_ir_node_ref_t value;
} store;
struct {
scc_ir_node_t *src_addr;
scc_ir_node_t *index;
scc_ir_node_ref_t src_addr;
scc_ir_node_ref_t index;
} get_ptr;
struct {
scc_ir_node_t *src_addr;
scc_ir_node_t *index;
scc_ir_node_ref_t src_addr;
scc_ir_node_ref_t index;
} get_elem_ptr;
struct {
scc_ir_op_type_t op;
scc_ir_node_t *lhs;
scc_ir_node_t *rhs;
scc_ir_node_ref_t lhs;
scc_ir_node_ref_t rhs;
} op;
struct {
scc_ir_node_t *cond;
scc_ir_bblock_t *true_bblock;
scc_ir_bblock_t *false_bblock;
scc_ir_node_ref_t cond;
scc_ir_bblock_ref_t true_bblock;
scc_ir_bblock_ref_t false_bblock;
} branch;
struct {
scc_ir_bblock_t *target_bblock;
scc_ir_bblock_ref_t target_bblock;
} jump;
struct {
scc_ir_func_t *callee;
scc_ir_node_vec_t args;
scc_ir_func_ref_t callee;
scc_ir_node_ref_vec_t args;
} call;
struct {
scc_ir_node_t *ret_val;
scc_ir_node_ref_t ret_val;
} ret;
} data;
};
typedef struct {
scc_ir_node_vec_t global_vals;
scc_ir_func_vec_t funcs;
scc_ir_func_vec_t extern_funcs;
} ir_cprog_t;
typedef struct scc_ir_cprog {
scc_ir_node_ref_vec_t global_vals;
scc_ir_func_ref_vec_t func_defs;
scc_ir_node_ref_vec_t func_decls;
} scc_ir_cprog_t;
#endif /* __SCC_IR_DEF_H__ */

View File

@@ -1,16 +1,21 @@
#ifndef __SCC_IR_DUMP_H__
#define __SCC_IR_DUMP_H__
#include "ir_ctx.h"
#include "ir_def.h"
#include <tree_dump.h>
typedef struct {
scc_ir_cprog_ctx_t *ir_ctx;
scc_ir_cprog_t *cprog;
scc_tree_dump_ctx_t *dump_ctx;
} scc_ir_dump_ctx_t;
void scc_ir_dump_ctx_init();
void scc_ir_type_dump(scc_ir_dump_ctx_t *ctx, const scc_ir_type_t *in);
void scc_ir_bblock_dump(scc_ir_dump_ctx_t *ctx, const scc_ir_bblock_t *in);
void scc_ir_func_dump(scc_ir_dump_ctx_t *ctx, const scc_ir_func_t *in);
void scc_ir_node_dump(scc_ir_dump_ctx_t *ctx, scc_ir_node_t *in);
void scc_ir_cprog_dump(scc_ir_dump_ctx_t *ctx, ir_cprog_t *in);
void scc_ir_dump_node(scc_ir_dump_ctx_t *ctx, scc_ir_node_ref_t node_ref);
void scc_ir_dump_type(scc_ir_dump_ctx_t *ctx, scc_ir_type_ref_t type_ref);
void scc_ir_dump_bblock(scc_ir_dump_ctx_t *ctx, scc_ir_bblock_ref_t bblock_ref);
void scc_ir_dump_func(scc_ir_dump_ctx_t *ctx, scc_ir_func_ref_t func_ref);
void scc_ir_dump_cprog(scc_ir_dump_ctx_t *ctx);
#endif /* __SCC_IR_DUMP_H__ */

View File

@@ -1,27 +1,9 @@
#ifndef __SCC_IR_H__
#define __SCC_IR_H__
#include "ir_builder.h"
#include "ir_ctx.h"
#include "ir_def.h"
void scc_ir_type_init(scc_ir_type_t *in, scc_ir_type_tag_t tag);
void scc_ir_bblock_init(scc_ir_bblock_t *in, const char *label);
void scc_ir_func_init(scc_ir_func_t *in, const char *name);
// node name can be null ptr
void scc_ir_node_init(scc_ir_node_t *in, const char *name,
scc_ir_node_tag_t tag);
void scc_ir_cprog_init(ir_cprog_t *in);
scc_ir_type_t *scc_ir_type_alloc(scc_ir_type_tag_t tag);
scc_ir_bblock_t *scc_ir_bblock_alloc(const char *label);
scc_ir_func_t *scc_ir_func_alloc(const char *name);
scc_ir_node_t *scc_ir_node_alloc(const char *name, scc_ir_node_tag_t tag);
// scc_ir_type_t *scc_ir_type_alloc_with_ctx(scc_ir_type_tag_t tag);
// scc_ir_bblock_t *scc_ir_bblock_alloc_with_ctx(const char *label);
// scc_ir_func_t *scc_ir_func_alloc_with_ctx(const char *name);
// scc_ir_node_t *scc_ir_node_alloc_with_ctx(const char *name,
// scc_ir_node_tag_t tag);
#include <scc_utils.h>
#endif /* __SCC_IR_H__ */

View File

@@ -1,19 +1,19 @@
#include <scc_ir.h>
#include <ir_base.h>
void scc_ir_type_init(scc_ir_type_t *in, scc_ir_type_tag_t tag) {
Assert(in != null);
in->tag = tag;
switch (tag) {
case SCC_IR_TYPE_ARRAY:
in->data.array.base = null;
in->data.array.base = 0;
in->data.array.len = 0;
break;
case SCC_IR_TYPE_PTR:
in->data.pointer.base = null;
in->data.pointer.base = 0;
break;
case SCC_IR_TYPE_FUNC:
scc_vec_init(in->data.function.params);
in->data.function.ret_type = null;
in->data.function.ret_type = 0;
break;
case SCC_IR_TYPE_VOID:
case SCC_IR_TYPE_I32:
@@ -35,7 +35,7 @@ void scc_ir_func_init(scc_ir_func_t *in, const char *name) {
Assert(in != null);
Assert(name != null);
in->name = name;
in->type = null;
in->type = 0;
scc_vec_init(in->bblocks);
scc_vec_init(in->params);
}
@@ -46,7 +46,7 @@ void scc_ir_node_init(scc_ir_node_t *in, const char *name,
in->name = name;
in->tag = tag;
scc_vec_init(in->used_by);
in->type = null;
in->type = 0;
switch (tag) {
case SCC_IR_NODE_NULL:
@@ -56,38 +56,38 @@ void scc_ir_node_init(scc_ir_node_t *in, const char *name,
in->data.const_int.int32 = 0;
break;
case SCC_IR_NODE_ALLOC:
TODO();
// TODO();
break;
case SCC_IR_NODE_LOAD:
in->data.load.target = null;
in->data.load.target = 0;
break;
case SCC_IR_NODE_STORE:
in->data.store.target = null;
in->data.store.value = null;
in->data.store.target = 0;
in->data.store.value = 0;
break;
case SCC_IR_NODE_GET_PTR:
in->data.get_ptr.src_addr = null;
in->data.get_ptr.index = null;
in->data.get_ptr.src_addr = 0;
in->data.get_ptr.index = 0;
break;
case SCC_IR_NODE_OP:
in->data.op.op = IR_OP_EMPTY;
in->data.op.lhs = null;
in->data.op.rhs = null;
in->data.op.lhs = 0;
in->data.op.rhs = 0;
break;
case SCC_IR_NODE_BRANCH:
in->data.branch.cond = null;
in->data.branch.true_bblock = null;
in->data.branch.false_bblock = null;
in->data.branch.cond = 0;
in->data.branch.true_bblock = 0;
in->data.branch.false_bblock = 0;
break;
case SCC_IR_NODE_JUMP:
in->data.jump.target_bblock = null;
in->data.jump.target_bblock = 0;
break;
case SCC_IR_NODE_CALL:
scc_vec_init(in->data.call.args);
in->data.call.callee = null;
in->data.call.callee = 0;
break;
case SCC_IR_NODE_RET:
in->data.ret.ret_val = null;
in->data.ret.ret_val = 0;
break;
default:
UNREACHABLE();
@@ -95,34 +95,14 @@ void scc_ir_node_init(scc_ir_node_t *in, const char *name,
}
}
void scc_ir_cprog_init(ir_cprog_t *in) {
Assert(in != null);
scc_vec_init(in->extern_funcs);
scc_vec_init(in->funcs);
void scc_ir_cprog_init(scc_ir_cprog_t *in) {
scc_vec_init(in->func_decls);
scc_vec_init(in->func_defs);
scc_vec_init(in->global_vals);
}
scc_ir_type_t *scc_ir_type_alloc(scc_ir_type_tag_t tag) {
scc_ir_type_t *ret = scc_malloc(sizeof(scc_ir_type_t));
Assert(ret != null);
scc_ir_type_init(ret, tag);
return ret;
}
scc_ir_bblock_t *scc_ir_bblock_alloc(const char *label) {
scc_ir_bblock_t *ret = scc_malloc(sizeof(scc_ir_bblock_t));
Assert(ret != null);
scc_ir_bblock_init(ret, label);
return ret;
}
scc_ir_func_t *scc_ir_func_alloc(const char *name) {
scc_ir_func_t *ret = scc_malloc(sizeof(scc_ir_func_t));
Assert(ret != null);
scc_ir_func_init(ret, name);
return ret;
}
scc_ir_node_t *scc_ir_node_alloc(const char *name, scc_ir_node_tag_t tag) {
scc_ir_node_t *ret = scc_malloc(sizeof(scc_ir_node_t));
Assert(ret != null);
scc_ir_node_init(ret, name, tag);
return ret;
void scc_ir_cprog_drop(scc_ir_cprog_t *in) {
scc_vec_free(in->func_decls);
scc_vec_free(in->func_defs);
scc_vec_free(in->global_vals);
}

351
libs/ir/src/ir_builder.c Normal file
View File

@@ -0,0 +1,351 @@
#include <ir_builder.h>
#include <ir_builtin.h>
void scc_ir_builder_init(scc_ir_builder_t *builder) {
builder->current_bblock = SCC_IR_REF_NULL;
builder->current_func = SCC_IR_REF_NULL;
scc_ir_cprog_init(&builder->cprog);
scc_ir_ctx_init(&builder->ctx);
}
void scc_ir_builder_drop(scc_ir_builder_t *builder) {
scc_ir_cprog_drop(&builder->cprog);
scc_ir_ctx_drop(&builder->ctx);
}
scc_ir_func_ref_t scc_ir_builder_begin_func(scc_ir_builder_t *builder,
const char *name,
scc_ir_type_ref_t type,
const char **param_names) {
scc_ir_func_t func = {0};
// 初始化参数和基本块向量
func.name = name;
func.type = type;
scc_vec_init(func.params);
scc_vec_init(func.bblocks);
// 创建函数并设置为当前函数
scc_ir_func_ref_t func_ref = scc_ir_ctx_new_func(&builder->ctx, &func);
builder->current_func = func_ref;
// 如果提供了参数名称,则创建参数节点
if (param_names == null) {
return func_ref;
}
scc_ir_func_t *func_ptr = scc_ir_ctx_get_func(&builder->ctx, func_ref);
scc_ir_type_t *func_type = scc_ir_ctx_get_type(&builder->ctx, type);
if (func_type == null || func_type->tag != SCC_IR_TYPE_FUNC) {
LOG_ERROR("Invalid function type");
return func_ref;
}
scc_vec_foreach(func_type->data.function.params, i) {
scc_ir_type_ref_t param_type =
scc_vec_at(func_type->data.function.params, i);
scc_ir_node_t param_node = {0};
param_node.tag = SCC_IR_NODE_NULL; // 参数节点标记
param_node.type = param_type;
param_node.name = param_names[i];
scc_vec_init(param_node.used_by);
scc_ir_node_ref_t param_ref =
scc_ir_ctx_new_node(&builder->ctx, &param_node);
scc_vec_push(func_ptr->params, param_ref);
}
return func_ref;
}
void scc_ir_builder_end_func(scc_ir_builder_t *builder) {
scc_ir_func_t *func_ptr =
scc_ir_ctx_get_func(&builder->ctx, builder->current_func);
if (func_ptr == null) {
LOG_FATAL("Invalid function reference");
return;
}
if (scc_vec_size(func_ptr->bblocks) == 0) {
scc_vec_push(builder->cprog.func_decls, builder->current_func);
} else {
scc_vec_push(builder->cprog.func_defs, builder->current_func);
}
builder->current_func = 0;
}
scc_ir_func_ref_t scc_ir_builder_current_func(scc_ir_builder_t *builder) {
return builder->current_func;
}
scc_ir_bblock_ref_t scc_ir_builder_begin_bblock(scc_ir_builder_t *builder,
const char *label) {
scc_ir_bblock_t bblock = {0};
if (label) {
bblock.label = label;
} else {
// TODO 自动生成标签
char *auto_label = scc_malloc(sizeof(char) * 64);
if (auto_label)
LOG_FATAL("allocate memory failed");
static int auto_counter = 0;
scc_snprintf(auto_label, sizeof(auto_label), ".BB%d", auto_counter++);
bblock.label = auto_label;
}
scc_vec_init(bblock.instrs);
scc_ir_bblock_ref_t bblock_ref =
scc_ir_ctx_new_bblock(&builder->ctx, &bblock);
builder->current_bblock = bblock_ref;
// 将基本块添加到当前函数
scc_ir_func_t *current_func =
scc_ir_ctx_get_func(&builder->ctx, builder->current_func);
if (current_func) {
scc_vec_push(current_func->bblocks, bblock_ref);
}
return bblock_ref;
}
void scc_ir_builder_end_bblock(scc_ir_builder_t *builder) {
builder->current_bblock = 0;
}
void scc_ir_builder_set_current_bblock(scc_ir_builder_t *builder,
scc_ir_bblock_ref_t bblock) {
builder->current_bblock = bblock;
}
static void scc_ir_builder_add_instr(scc_ir_builder_t *builder,
scc_ir_node_ref_t node) {
scc_ir_bblock_t *current_bblock =
scc_ir_ctx_get_bblock(&builder->ctx, builder->current_bblock);
if (current_bblock) {
scc_vec_push(current_bblock->instrs, node);
} else {
LOG_ERROR("Current basic block is not set");
}
}
scc_ir_node_ref_t scc_ir_builder_alloca(scc_ir_builder_t *builder,
scc_ir_type_ref_t type,
const char *name) {
scc_ir_node_t alloc_node = {0};
alloc_node.tag = SCC_IR_NODE_ALLOC;
alloc_node.type = scc_ir_ctx_new_type(
&builder->ctx,
&(scc_ir_type_t){.tag = SCC_IR_TYPE_PTR, .data.pointer.base = type});
alloc_node.name = name;
scc_ir_node_ref_t node_ref =
scc_ir_ctx_new_node(&builder->ctx, &alloc_node);
// 添加到当前基本块
scc_ir_builder_add_instr(builder, node_ref);
return node_ref;
}
scc_ir_node_ref_t scc_ir_builder_load(scc_ir_builder_t *builder,
scc_ir_node_ref_t ptr) {
scc_ir_node_t load_node = {0};
load_node.tag = SCC_IR_NODE_LOAD;
load_node.data.load.target = ptr;
// 设置类型为指针指向的类型
scc_ir_node_t *ptr_node = scc_ir_ctx_get_node(&builder->ctx, ptr);
if (ptr_node) {
scc_ir_type_t *ptr_type =
scc_ir_ctx_get_type(&builder->ctx, ptr_node->type);
if (ptr_type && ptr_type->tag == SCC_IR_TYPE_PTR) {
load_node.type = ptr_type->data.pointer.base;
}
}
scc_ir_node_ref_t node_ref = scc_ir_ctx_new_node(&builder->ctx, &load_node);
// 添加到当前基本块
scc_ir_builder_add_instr(builder, node_ref);
return node_ref;
}
scc_ir_node_ref_t scc_ir_builder_store(scc_ir_builder_t *builder,
scc_ir_node_ref_t ptr,
scc_ir_node_ref_t value) {
scc_ir_node_t store_node = {0};
store_node.tag = SCC_IR_NODE_STORE;
store_node.data.store.target = ptr;
store_node.data.store.value = value;
scc_ir_node_ref_t node_ref =
scc_ir_ctx_new_node(&builder->ctx, &store_node);
// 添加到当前基本块
scc_ir_builder_add_instr(builder, node_ref);
return node_ref;
}
scc_ir_node_ref_t scc_ir_builder_get_ptr(scc_ir_builder_t *builder,
scc_ir_node_ref_t ptr,
scc_ir_node_ref_t index) {
scc_ir_node_t get_ptr_node = {0};
get_ptr_node.tag = SCC_IR_NODE_GET_PTR;
get_ptr_node.data.get_ptr.src_addr = ptr;
get_ptr_node.data.get_ptr.index = index;
// 类型应与源地址相同(都是指针)
scc_ir_node_t *src_node = scc_ir_ctx_get_node(&builder->ctx, ptr);
if (src_node) {
get_ptr_node.type = src_node->type;
}
scc_ir_node_ref_t node_ref =
scc_ir_ctx_new_node(&builder->ctx, &get_ptr_node);
// 添加到当前基本块
scc_ir_builder_add_instr(builder, node_ref);
return node_ref;
}
scc_ir_node_ref_t scc_ir_builder_binop(scc_ir_builder_t *builder,
scc_ir_op_type_t op,
scc_ir_node_ref_t lhs,
scc_ir_node_ref_t rhs) {
scc_ir_node_t binop_node = {0};
binop_node.tag = SCC_IR_NODE_OP;
binop_node.data.op.op = op;
binop_node.data.op.lhs = lhs;
binop_node.data.op.rhs = rhs;
// 类型通常与操作数相同(对于算术运算)
scc_ir_node_t *lhs_node = scc_ir_ctx_get_node(&builder->ctx, lhs);
if (lhs_node) {
binop_node.type = lhs_node->type;
}
scc_ir_node_ref_t node_ref =
scc_ir_ctx_new_node(&builder->ctx, &binop_node);
// 添加到当前基本块
scc_ir_builder_add_instr(builder, node_ref);
return node_ref;
}
scc_ir_node_ref_t scc_ir_builder_cmp(scc_ir_builder_t *builder,
scc_ir_op_type_t op, scc_ir_node_ref_t lhs,
scc_ir_node_ref_t rhs) {
scc_ir_node_t cmp_node = {0};
cmp_node.tag = SCC_IR_NODE_OP;
cmp_node.data.op.op = op;
cmp_node.data.op.lhs = lhs;
cmp_node.data.op.rhs = rhs;
// 比较操作的结果通常是布尔值
cmp_node.type = scc_ir_ctx_get_builtin_i32(&builder->ctx);
scc_ir_node_ref_t node_ref = scc_ir_ctx_new_node(&builder->ctx, &cmp_node);
// 添加到当前基本块
scc_ir_builder_add_instr(builder, node_ref);
return node_ref;
}
scc_ir_node_ref_t scc_ir_builder_jump(scc_ir_builder_t *builder,
scc_ir_bblock_ref_t target) {
scc_ir_node_t jump_node = {0};
jump_node.tag = SCC_IR_NODE_JUMP;
jump_node.data.jump.target_bblock = target;
scc_ir_node_ref_t node_ref = scc_ir_ctx_new_node(&builder->ctx, &jump_node);
// 添加到当前基本块
scc_ir_builder_add_instr(builder, node_ref);
return node_ref;
}
scc_ir_node_ref_t scc_ir_builder_branch(scc_ir_builder_t *builder,
scc_ir_node_ref_t cond,
scc_ir_bblock_ref_t true_target,
scc_ir_bblock_ref_t false_target) {
scc_ir_node_t branch_node = {0};
branch_node.tag = SCC_IR_NODE_BRANCH;
branch_node.data.branch.cond = cond;
branch_node.data.branch.true_bblock = true_target;
branch_node.data.branch.false_bblock = false_target;
scc_ir_node_ref_t node_ref =
scc_ir_ctx_new_node(&builder->ctx, &branch_node);
// 添加到当前基本块
scc_ir_builder_add_instr(builder, node_ref);
return node_ref;
}
scc_ir_node_ref_t scc_ir_builder_call(scc_ir_builder_t *builder,
scc_ir_func_ref_t callee,
const scc_ir_node_ref_t *args,
usize arg_count) {
scc_ir_node_t call_node = {0};
call_node.tag = SCC_IR_NODE_CALL;
call_node.data.call.callee = callee;
scc_vec_init(call_node.data.call.args);
for (usize i = 0; i < arg_count; i++) {
scc_vec_push(call_node.data.call.args, args[i]);
}
// 设置返回类型为被调用函数的返回类型
scc_ir_func_t *callee_func = scc_ir_ctx_get_func(&builder->ctx, callee);
if (callee_func) {
scc_ir_type_t *func_type =
scc_ir_ctx_get_type(&builder->ctx, callee_func->type);
if (func_type && func_type->tag == SCC_IR_TYPE_FUNC) {
call_node.type = func_type->data.function.ret_type;
}
}
scc_ir_node_ref_t node_ref = scc_ir_ctx_new_node(&builder->ctx, &call_node);
// 添加到当前基本块
scc_ir_builder_add_instr(builder, node_ref);
return node_ref;
}
scc_ir_node_ref_t scc_ir_builder_ret(scc_ir_builder_t *builder,
scc_ir_node_ref_t value) {
scc_ir_node_t ret_node = {0};
ret_node.tag = SCC_IR_NODE_RET;
ret_node.data.ret.ret_val = value;
scc_ir_node_ref_t node_ref = scc_ir_ctx_new_node(&builder->ctx, &ret_node);
// 添加到当前基本块
scc_ir_builder_add_instr(builder, node_ref);
return node_ref;
}
scc_ir_node_ref_t scc_ir_builder_ret_void(scc_ir_builder_t *builder) {
scc_ir_node_t ret_node = {0};
ret_node.tag = SCC_IR_NODE_RET;
ret_node.data.ret.ret_val = 0; // 无返回值
scc_ir_node_ref_t node_ref = scc_ir_ctx_new_node(&builder->ctx, &ret_node);
// 添加到当前基本块
scc_ir_builder_add_instr(builder, node_ref);
return node_ref;
}

345
libs/ir/src/ir_ctx.c Normal file
View File

@@ -0,0 +1,345 @@
#include "ir_ctx.h"
#include "ir_builtin.h"
/**
* @brief 哈希混合函数类似Rust的hash combine
*
* Rust的默认哈希实现SipHash 1-3使用旋转和异或
* 这里使用简单的FNV-1a变体类似于Rust的`#[derive(Hash)]`
*/
static inline u32 scc_hash_mix(u32 seed, u32 value) {
// FNV-1a风格混合
return (seed ^ value) * 16777619u;
}
static u32 hash_key(const void *key) { return (u32)(usize)key; }
static int cmp_key(const void *key1, const void *key2) {
return (u32)(usize)key1 != (u32)(usize)key2;
}
static u32 hash_type(const scc_ir_type_t *key) {
// 初始哈希tag
u32 hash = (u32)key->tag;
switch (key->tag) {
case SCC_IR_TYPE_VOID:
case SCC_IR_TYPE_I1:
case SCC_IR_TYPE_I8:
case SCC_IR_TYPE_I16:
case SCC_IR_TYPE_I32:
case SCC_IR_TYPE_I64:
case SCC_IR_TYPE_I128:
case SCC_IR_TYPE_F16:
case SCC_IR_TYPE_F32:
case SCC_IR_TYPE_F64:
case SCC_IR_TYPE_F128:
// 基本类型只有tag
break;
case SCC_IR_TYPE_PTR:
hash = scc_hash_mix(hash, (u32)key->data.array.base);
break;
case SCC_IR_TYPE_ARRAY:
hash = scc_hash_mix(hash, (u32)key->data.array.base);
hash = scc_hash_mix(hash, (u32)key->data.array.len);
break;
case SCC_IR_TYPE_FUNC:
// 注意:这里需要递归哈希参数类型
hash = scc_hash_mix(hash, (u32)key->data.function.ret_type);
for (usize i = 0; i < key->data.function.params.size; i++) {
hash = scc_hash_mix(hash, (u32)key->data.function.params.data[i]);
}
hash = scc_hash_mix(hash, (u32)key->data.function.params.size);
break;
case SCC_IR_TYPE_STRUCT:
case SCC_IR_TYPE_VECTOR:
default:
UNREACHABLE();
return 0;
}
return hash;
}
static int cmp_type(const scc_ir_type_t *key1, const scc_ir_type_t *key2) {
// tag不同
if (key1->tag != key2->tag) {
return 1;
}
switch (key1->tag) {
case SCC_IR_TYPE_VOID:
case SCC_IR_TYPE_I1:
case SCC_IR_TYPE_I8:
case SCC_IR_TYPE_I16:
case SCC_IR_TYPE_I32:
case SCC_IR_TYPE_I64:
case SCC_IR_TYPE_I128:
case SCC_IR_TYPE_F16:
case SCC_IR_TYPE_F32:
case SCC_IR_TYPE_F64:
case SCC_IR_TYPE_F128:
return 0; // 基本类型tag相同即可
case SCC_IR_TYPE_PTR:
return key1->data.pointer.base != key2->data.pointer.base;
case SCC_IR_TYPE_ARRAY:
return (key1->data.array.base != key2->data.array.base) ||
(key1->data.array.len != key2->data.array.len);
case SCC_IR_TYPE_FUNC: {
if (key1->data.function.ret_type != key2->data.function.ret_type) {
return 1;
}
if (key1->data.function.params.size !=
key2->data.function.params.size) {
return 1;
}
for (usize i = 0; i < key1->data.function.params.size; i++) {
if (key1->data.function.params.data[i] !=
key2->data.function.params.data[i]) {
return 1;
}
}
return 0;
}
default:
UNREACHABLE();
return 1;
}
return 1;
}
void scc_ir_ctx_init(scc_ir_cprog_ctx_t *ctx) {
// 初始化向量
scc_vec_init(ctx->nodes);
scc_vec_init(ctx->types);
scc_vec_init(ctx->bblocks);
scc_vec_init(ctx->funcs);
// 设置哈希函数
ctx->uid2nodes.hash_func = hash_key;
ctx->uid2nodes.key_cmp = cmp_key;
ctx->uid2types.hash_func = hash_key;
ctx->uid2types.key_cmp = cmp_key;
ctx->uid2bblocks.hash_func = hash_key;
ctx->uid2bblocks.key_cmp = cmp_key;
ctx->uid2funcs.hash_func = hash_key;
ctx->uid2funcs.key_cmp = cmp_key;
// 初始化哈希表
scc_hashtable_init(&ctx->uid2nodes);
scc_hashtable_init(&ctx->uid2types);
scc_hashtable_init(&ctx->uid2bblocks);
scc_hashtable_init(&ctx->uid2funcs);
ctx->type_uniquing.hash_func = (void *)hash_type;
ctx->type_uniquing.key_cmp = (void *)cmp_type;
scc_hashtable_init(&ctx->type_uniquing);
// 预留UID 0 作为无效引用
ctx->node_uid = 1;
ctx->type_uid = 1;
ctx->bblock_uid = 1;
ctx->func_uid = 1;
}
void scc_ir_ctx_drop(scc_ir_cprog_ctx_t *ctx) {
// 释放所有实体的内部内存
for (usize i = 0; i < ctx->nodes.size; i++) {
scc_ir_node_t *node = &ctx->nodes.data[i];
scc_vec_free(node->used_by);
if (node->tag == SCC_IR_NODE_CALL) {
scc_vec_free(node->data.call.args);
}
}
for (usize i = 0; i < ctx->types.size; i++) {
scc_ir_type_t *type = &ctx->types.data[i];
if (type->tag == SCC_IR_TYPE_FUNC) {
scc_vec_free(type->data.function.params);
}
}
for (usize i = 0; i < ctx->bblocks.size; i++) {
scc_ir_bblock_t *bblock = &ctx->bblocks.data[i];
scc_vec_free(bblock->instrs);
}
for (usize i = 0; i < ctx->funcs.size; i++) {
scc_ir_func_t *func = &ctx->funcs.data[i];
scc_vec_free(func->params);
scc_vec_free(func->bblocks);
}
// 释放向量
scc_vec_free(ctx->nodes);
scc_vec_free(ctx->types);
scc_vec_free(ctx->bblocks);
scc_vec_free(ctx->funcs);
// 释放哈希表
scc_hashtable_drop(&ctx->uid2nodes);
scc_hashtable_drop(&ctx->uid2types);
scc_hashtable_drop(&ctx->uid2bblocks);
scc_hashtable_drop(&ctx->uid2funcs);
}
void scc_ir_ctx_reset(scc_ir_cprog_ctx_t *ctx) {
// 先销毁再重新初始化
scc_ir_ctx_drop(ctx);
scc_ir_ctx_init(ctx);
}
// 辅助宏:创建实体并添加到哈希表
#define CREATE_ENTITY(ctx, vec, uid, data, hashtable) \
do { \
/* 分配新UID */ \
unsigned new_uid = (ctx)->uid++; \
/* 添加到向量 */ \
scc_vec_push((vec), *(data)); \
/* 添加到哈希表 */ \
scc_hashtable_set(&(ctx)->hashtable, (const void *)(usize)new_uid, \
(void *)(usize)(scc_vec_size(vec) - 1)); \
return new_uid; \
} while (0)
scc_ir_type_ref_t scc_ir_ctx_new_type(scc_ir_cprog_ctx_t *ctx,
const scc_ir_type_t *type) {
// 首先检查去重表
void *existing = scc_hashtable_get(&ctx->type_uniquing, type);
if (existing) {
return (scc_ir_type_ref_t)(uintptr_t)existing;
}
// 创建新类型
unsigned new_uid = ctx->type_uid++;
scc_vec_push(ctx->types, *type);
// 添加到UID映射
usize idx = ctx->types.size - 1;
scc_hashtable_set(&ctx->uid2types, &new_uid, (void *)idx);
// 添加到去重表
scc_hashtable_set(&ctx->type_uniquing,
&ctx->types.data[idx], // 使用向量中的地址作为键
(void *)(uintptr_t)new_uid);
return new_uid;
}
scc_ir_node_ref_t scc_ir_ctx_new_node(scc_ir_cprog_ctx_t *ctx,
const scc_ir_node_t *node) {
CREATE_ENTITY(ctx, ctx->nodes, node_uid, node, uid2nodes);
}
scc_ir_bblock_ref_t scc_ir_ctx_new_bblock(scc_ir_cprog_ctx_t *ctx,
const scc_ir_bblock_t *bblock) {
CREATE_ENTITY(ctx, ctx->bblocks, bblock_uid, bblock, uid2bblocks);
}
scc_ir_func_ref_t scc_ir_ctx_new_func(scc_ir_cprog_ctx_t *ctx,
const scc_ir_func_t *func) {
CREATE_ENTITY(ctx, ctx->funcs, func_uid, func, uid2funcs);
}
#undef CREATE_ENTITY
// 辅助宏:从哈希表获取索引
#define GET_ENTITY_INDEX(ctx, ref, hashtable) \
((usize)scc_hashtable_get(&(ctx)->hashtable, (void *)(usize)ref))
scc_ir_type_t *scc_ir_ctx_get_type(scc_ir_cprog_ctx_t *ctx,
scc_ir_type_ref_t ref) {
if (ref == 0)
return null;
usize idx = GET_ENTITY_INDEX(ctx, ref, uid2types);
if (idx >= ctx->types.size)
return null;
return &ctx->types.data[idx];
}
scc_ir_node_t *scc_ir_ctx_get_node(scc_ir_cprog_ctx_t *ctx,
scc_ir_node_ref_t ref) {
if (ref == 0)
return null;
usize idx = GET_ENTITY_INDEX(ctx, ref, uid2nodes);
if (idx >= ctx->nodes.size)
return null;
return &ctx->nodes.data[idx];
}
scc_ir_bblock_t *scc_ir_ctx_get_bblock(scc_ir_cprog_ctx_t *ctx,
scc_ir_bblock_ref_t ref) {
if (ref == 0)
return null;
usize idx = GET_ENTITY_INDEX(ctx, ref, uid2bblocks);
if (idx >= ctx->bblocks.size)
return null;
return &ctx->bblocks.data[idx];
}
scc_ir_func_t *scc_ir_ctx_get_func(scc_ir_cprog_ctx_t *ctx,
scc_ir_func_ref_t ref) {
if (ref == 0)
return null;
usize idx = GET_ENTITY_INDEX(ctx, ref, uid2funcs);
if (idx >= ctx->funcs.size)
return null;
return &ctx->funcs.data[idx];
}
#undef GET_ENTITY_INDEX
// 内置类型和常量缓存
static scc_ir_type_ref_t cached_i32_type = 0;
static scc_ir_node_ref_t cached_zero_const = 0;
scc_ir_type_ref_t scc_ir_ctx_get_builtin_i32(scc_ir_cprog_ctx_t *ctx) {
if (cached_i32_type == 0) {
scc_ir_type_t i32_type = {.tag = SCC_IR_TYPE_I32};
cached_i32_type = scc_ir_ctx_new_type(ctx, &i32_type);
}
return cached_i32_type;
}
scc_ir_node_ref_t scc_ir_ctx_get_builtin_zero(scc_ir_cprog_ctx_t *ctx) {
if (cached_zero_const == 0) {
scc_ir_node_t zero_node = {.tag = SCC_IR_NODE_CONST_INT,
.type = scc_ir_ctx_get_builtin_i32(ctx),
.name = "zero",
.data.const_int.int32 = 0};
cached_zero_const = scc_ir_ctx_new_node(ctx, &zero_node);
}
return cached_zero_const;
}
// 常量池(简化版)
typedef struct {
i32 value;
scc_ir_node_ref_t ref;
} i32_const_entry_t;
scc_ir_node_ref_t scc_ir_ctx_get_i32_const(scc_ir_cprog_ctx_t *ctx, i32 value) {
// 如果是0使用内置zero
if (value == 0) {
return scc_ir_ctx_get_builtin_zero(ctx);
}
// TODO: 实现常量池哈希表
// 这里简化实现,每次都创建新常量
scc_ir_node_t const_node = {.tag = SCC_IR_NODE_CONST_INT,
.type = scc_ir_ctx_get_builtin_i32(ctx),
.data.const_int.int32 = value};
const_node.name = "";
return scc_ir_ctx_new_node(ctx, &const_node);
}
scc_ir_node_ref_t scc_ir_ctx_get_null_const(scc_ir_cprog_ctx_t *ctx,
scc_ir_type_ref_t ptr_type) {
return 1;
}

View File

@@ -1,13 +1,522 @@
#include <ir_ctx.h>
#include <ir_dump.h>
void scc_ir_type_dump(scc_ir_dump_ctx_t *ctx, const scc_ir_type_t *in) {
return;
#define PRINT_VALUE(ctx, fmt, value) \
SCC_TREE_DUMP_PRINT_PURE(ctx, ctx->value_color, fmt, value)
#define PRINT_NODE(ctx, name) \
SCC_TREE_DUMP_PRINT_PURE(ctx, ctx->node_color, "%s", name)
#define PRINT_QUOTED_VALUE(ctx, str) \
SCC_TREE_DUMP_PRINT_AROUND(ctx, ctx->value_color, "'", "%s", str)
// 获取IR节点类型的字符串表示
static const char *get_node_type_str(scc_ir_node_tag_t tag) {
static const char *node_types[] = {
[SCC_IR_NODE_NULL] = "Null", [SCC_IR_NODE_CONST_INT] = "ConstInt",
[SCC_IR_NODE_ALLOC] = "Alloc", [SCC_IR_NODE_LOAD] = "Load",
[SCC_IR_NODE_STORE] = "Store", [SCC_IR_NODE_GET_PTR] = "GetElementPtr",
[SCC_IR_NODE_OP] = "Op", [SCC_IR_NODE_BRANCH] = "Branch",
[SCC_IR_NODE_JUMP] = "Jump", [SCC_IR_NODE_CALL] = "Call",
[SCC_IR_NODE_RET] = "Return",
};
if (tag >= 0 && tag < sizeof(node_types) / sizeof(node_types[0]) &&
node_types[tag] != NULL) {
return node_types[tag];
}
return "UnknownIRNode";
}
void scc_ir_bblock_dump(scc_ir_dump_ctx_t *ctx, const scc_ir_bblock_t *in) {
return;
// 获取操作符字符串
static const char *get_op_str(scc_ir_op_type_t op) {
static const char *ops[] = {
[IR_OP_EMPTY] = "empty", [IR_OP_NEQ] = "!=", [IR_OP_EQ] = "==",
[IR_OP_GT] = ">", [IR_OP_LT] = "<", [IR_OP_GE] = ">=",
[IR_OP_LE] = "<=", [IR_OP_ADD] = "+", [IR_OP_SUB] = "-",
[IR_OP_MUL] = "*", [IR_OP_DIV] = "/", [IR_OP_MOD] = "%",
[IR_OP_AND] = "&", [IR_OP_OR] = "|", [IR_OP_XOR] = "^",
[IR_OP_NOT] = "~", [IR_OP_SHL] = "<<", [IR_OP_SHR] = ">>",
[IR_OP_SAR] = ">>a", // Arithmetic shift right
};
if (op >= 0 && op < sizeof(ops) / sizeof(ops[0]) && ops[op] != NULL) {
return ops[op];
}
return "<unknown_op>";
}
void scc_ir_func_dump(scc_ir_dump_ctx_t *ctx, const scc_ir_func_t *in) {
return;
// 获取类型标签字符串
static const char *get_type_tag_str(scc_ir_type_tag_t tag) {
static const char *type_tags[] = {
[SCC_IR_TYPE_VOID] = "void", [SCC_IR_TYPE_I1] = "i1",
[SCC_IR_TYPE_I8] = "i8", [SCC_IR_TYPE_I16] = "i16",
[SCC_IR_TYPE_I32] = "i32", [SCC_IR_TYPE_I64] = "i64",
[SCC_IR_TYPE_I128] = "i128", [SCC_IR_TYPE_F16] = "f16",
[SCC_IR_TYPE_F32] = "f32", [SCC_IR_TYPE_F64] = "f64",
[SCC_IR_TYPE_F128] = "f128", [SCC_IR_TYPE_PTR] = "ptr",
[SCC_IR_TYPE_ARRAY] = "array", [SCC_IR_TYPE_FUNC] = "func",
[SCC_IR_TYPE_STRUCT] = "struct", [SCC_IR_TYPE_VECTOR] = "vector",
};
if (tag >= 0 && tag < sizeof(type_tags) / sizeof(type_tags[0]) &&
type_tags[tag] != NULL) {
return type_tags[tag];
}
return "<unknown_type>";
}
// 递归转储辅助函数(使用引用)
static inline void dump_child_node_ref(scc_ir_dump_ctx_t *ctx,
scc_ir_node_ref_t child_ref,
cbool is_last) {
if (!child_ref)
return;
scc_tree_dump_push_level(ctx->dump_ctx, is_last);
scc_ir_dump_node(ctx, child_ref);
scc_tree_dump_pop_level(ctx->dump_ctx);
}
// 转储常量整数节点
static void dump_const_int_node(scc_ir_dump_ctx_t *ctx,
const scc_ir_node_t *node) {
scc_tree_dump_push_level(ctx->dump_ctx, true);
scc_tree_print_indent(ctx->dump_ctx);
scc_printf("%d\n", node->data.const_int.int32);
scc_tree_dump_pop_level(ctx->dump_ctx);
}
// 转储操作节点
static void dump_op_node(scc_ir_dump_ctx_t *ctx, const scc_ir_node_t *node) {
// 打印操作符
scc_tree_dump_push_level(ctx->dump_ctx, false);
scc_tree_print_indent(ctx->dump_ctx);
SCC_TREE_DUMP_PRINT_PURE(ctx->dump_ctx, ctx->dump_ctx->node_color,
"op: %s\n", get_op_str(node->data.op.op));
scc_tree_dump_pop_level(ctx->dump_ctx);
// 左操作数
if (node->data.op.lhs) {
dump_child_node_ref(ctx, node->data.op.lhs,
node->data.op.rhs ? false : true);
}
// 右操作数
if (node->data.op.rhs) {
dump_child_node_ref(ctx, node->data.op.rhs, true);
}
}
// 转储加载节点
static void dump_load_node(scc_ir_dump_ctx_t *ctx, const scc_ir_node_t *node) {
// PRINT_NODE(ctx->dump_ctx, "load");
if (node->data.load.target) {
dump_child_node_ref(ctx, node->data.load.target, true);
}
}
// 转储存储节点
static void dump_store_node(scc_ir_dump_ctx_t *ctx, const scc_ir_node_t *node) {
// PRINT_NODE(ctx->dump_ctx, "store");
// 输出存储位置
if (node->data.store.target) {
dump_child_node_ref(ctx, node->data.store.target, false);
}
// 输出存储的值
if (node->data.store.value) {
dump_child_node_ref(ctx, node->data.store.value, true);
}
}
// 转储获取指针节点
static void dump_get_ptr_node(scc_ir_dump_ctx_t *ctx,
const scc_ir_node_t *node) {
// PRINT_NODE(ctx->dump_ctx, "get_ptr");
// 输出源地址
if (node->data.get_ptr.src_addr) {
dump_child_node_ref(ctx, node->data.get_ptr.src_addr, false);
}
// 输出索引
if (node->data.get_ptr.index) {
dump_child_node_ref(ctx, node->data.get_ptr.index, true);
}
}
// 转储分支节点
static void dump_branch_node(scc_ir_dump_ctx_t *ctx,
const scc_ir_node_t *node) {
// PRINT_NODE(ctx->dump_ctx, "branch");
// 输出条件
if (node->data.branch.cond) {
dump_child_node_ref(ctx, node->data.branch.cond, false);
}
// 输出真分支块
if (node->data.branch.true_bblock) {
scc_ir_bblock_t *true_bblock =
scc_ir_ctx_get_bblock(ctx->ir_ctx, node->data.branch.true_bblock);
if (true_bblock) {
scc_tree_print_indent(ctx->dump_ctx);
PRINT_NODE(ctx->dump_ctx, "TrueBlock: ");
PRINT_QUOTED_VALUE(ctx->dump_ctx, true_bblock->label
? true_bblock->label
: "<unnamed>");
}
}
// 输出假分支块
if (node->data.branch.false_bblock) {
scc_ir_bblock_t *false_bblock =
scc_ir_ctx_get_bblock(ctx->ir_ctx, node->data.branch.false_bblock);
if (false_bblock) {
scc_tree_print_indent(ctx->dump_ctx);
PRINT_NODE(ctx->dump_ctx, "FalseBlock: ");
PRINT_QUOTED_VALUE(ctx->dump_ctx, false_bblock->label
? false_bblock->label
: "<unnamed>");
}
}
}
// 转储跳转节点
static void dump_jump_node(scc_ir_dump_ctx_t *ctx, const scc_ir_node_t *node) {
// PRINT_NODE(ctx->dump_ctx, "jump");
if (node->data.jump.target_bblock) {
scc_ir_bblock_t *target_bblock =
scc_ir_ctx_get_bblock(ctx->ir_ctx, node->data.jump.target_bblock);
if (target_bblock) {
scc_printf("to '%s'", target_bblock->label ? target_bblock->label
: "<unnamed>");
} else {
scc_printf("to invalid block");
}
} else {
scc_printf("to NULL");
}
}
// 转储调用节点
static void dump_call_node(scc_ir_dump_ctx_t *ctx, const scc_ir_node_t *node) {
// PRINT_NODE(ctx->dump_ctx, "call");
if (node->data.call.callee) {
scc_ir_func_t *callee =
scc_ir_ctx_get_func(ctx->ir_ctx, node->data.call.callee);
if (callee) {
scc_printf("func='%s'", callee->name ? callee->name : "<unnamed>");
} else {
scc_printf("func=<invalid>");
}
} else {
scc_printf("func=NULL");
}
if (scc_vec_size(node->data.call.args) > 0) {
scc_printf("\n");
}
// 输出参数
for (usize i = 0; i < scc_vec_size(node->data.call.args); i++) {
cbool is_last = (i + 1 == scc_vec_size(node->data.call.args));
scc_tree_dump_push_level(ctx->dump_ctx, is_last);
scc_ir_node_ref_t arg_ref = scc_vec_at(node->data.call.args, i);
dump_child_node_ref(ctx, arg_ref, is_last);
scc_tree_dump_pop_level(ctx->dump_ctx);
}
}
// 转储返回节点
static void dump_ret_node(scc_ir_dump_ctx_t *ctx, const scc_ir_node_t *node) {
// PRINT_NODE(ctx->dump_ctx, "ret");
if (node->data.ret.ret_val) {
dump_child_node_ref(ctx, node->data.ret.ret_val, true);
}
}
void scc_ir_dump_node(scc_ir_dump_ctx_t *ctx, scc_ir_node_ref_t node_ref) {
scc_ir_node_t *node = scc_ir_ctx_get_node(ctx->ir_ctx, node_ref);
if (!node) {
LOG_ERROR("Invalid node ref");
return;
}
scc_tree_print_indent(ctx->dump_ctx);
PRINT_NODE(ctx->dump_ctx, get_node_type_str(node->tag));
if (node->name && node->name[0]) {
PRINT_VALUE(ctx->dump_ctx, " [%s]", node->name);
}
if (node->type) {
scc_printf(" : ");
scc_ir_type_t *type = scc_ir_ctx_get_type(ctx->ir_ctx, node->type);
if (type) {
PRINT_VALUE(ctx->dump_ctx, "%s", get_type_tag_str(type->tag));
}
}
scc_printf("\n");
// 根据节点类型输出特定信息
switch (node->tag) {
case SCC_IR_NODE_NULL:
break;
case SCC_IR_NODE_CONST_INT:
dump_const_int_node(ctx, node);
break;
case SCC_IR_NODE_ALLOC:
break;
case SCC_IR_NODE_LOAD:
dump_load_node(ctx, node);
break;
case SCC_IR_NODE_STORE:
dump_store_node(ctx, node);
break;
case SCC_IR_NODE_GET_PTR:
dump_get_ptr_node(ctx, node);
break;
case SCC_IR_NODE_OP:
dump_op_node(ctx, node);
break;
case SCC_IR_NODE_BRANCH:
dump_branch_node(ctx, node);
break;
case SCC_IR_NODE_JUMP:
dump_jump_node(ctx, node);
break;
case SCC_IR_NODE_CALL:
dump_call_node(ctx, node);
break;
case SCC_IR_NODE_RET:
dump_ret_node(ctx, node);
break;
default:
PRINT_QUOTED_VALUE(ctx->dump_ctx, "unknown");
scc_printf("tag(%d)", node->tag);
break;
}
}
// 转储类型信息
void scc_ir_dump_type(scc_ir_dump_ctx_t *ctx, scc_ir_type_ref_t type_ref) {
// impl fmt::Display for TypeKind {
// fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
// match self {
// TypeKind::Int32 => write!(f, "i32"),
// TypeKind::Unit => write!(f, "unit"),
// TypeKind::Array(t, len) => write!(f, "[{}, {}]", t, len),
// TypeKind::Pointer(t) => write!(f, "*{}", t),
// TypeKind::Function(params, ret) => {
// write!(f, "(")?;
// let mut first = true;
// for param in params {
// if !first {
// write!(f, ", ")?;
// }
// write!(f, "{}", param)?;
// first = false;
// }
// if !ret.is_unit() {
// write!(f, "): {}", ret)
// } else {
// write!(f, ")")
// }
// }
// }
// }
// }
if (!ctx || !type_ref) {
LOG_ERROR("invalid parameter");
return;
}
scc_ir_type_t *type = scc_ir_ctx_get_type(ctx->ir_ctx, type_ref);
if (!type) {
LOG_ERROR("invalid type ref");
return;
}
scc_tree_print_indent(ctx->dump_ctx);
PRINT_NODE(ctx->dump_ctx, "Type: ");
PRINT_QUOTED_VALUE(ctx->dump_ctx, get_type_tag_str(type->tag));
scc_printf("\n");
// 递归转储子类型
switch (type->tag) {
case SCC_IR_TYPE_PTR:
if (type->data.pointer.base) {
scc_tree_dump_push_level(ctx->dump_ctx, true);
scc_ir_dump_type(ctx, type->data.pointer.base);
scc_tree_dump_pop_level(ctx->dump_ctx);
}
break;
case SCC_IR_TYPE_ARRAY:
if (type->data.array.len > 0) {
scc_tree_print_indent(ctx->dump_ctx);
SCC_TREE_DUMP_PRINT_PURE(ctx->dump_ctx, ctx->dump_ctx->node_color,
"Array Length: %zu\n",
type->data.array.len);
}
if (type->data.array.base) {
scc_tree_dump_push_level(ctx->dump_ctx, true);
scc_ir_dump_type(ctx, type->data.array.base);
scc_tree_dump_pop_level(ctx->dump_ctx);
}
break;
case SCC_IR_TYPE_FUNC:
// 先输出参数类型
for (usize i = 0; i < scc_vec_size(type->data.function.params); i++) {
cbool is_last = (i + 1 == scc_vec_size(type->data.function.params));
scc_tree_dump_push_level(ctx->dump_ctx, is_last);
scc_ir_type_ref_t param_type_ref =
scc_vec_at(type->data.function.params, i);
scc_ir_dump_type(ctx, param_type_ref);
scc_tree_dump_pop_level(ctx->dump_ctx);
}
// 再输出返回类型
if (type->data.function.ret_type) {
scc_tree_dump_push_level(ctx->dump_ctx, true);
scc_ir_dump_type(ctx, type->data.function.ret_type);
scc_tree_dump_pop_level(ctx->dump_ctx);
}
break;
case SCC_IR_TYPE_STRUCT:
// 结构体处理
break;
case SCC_IR_TYPE_VECTOR:
// 向量处理
break;
default:
break;
}
}
// 转储基本块
void scc_ir_dump_bblock(scc_ir_dump_ctx_t *ctx,
scc_ir_bblock_ref_t bblock_ref) {
if (!ctx || !bblock_ref) {
LOG_ERROR("invalid parameter");
return;
}
scc_ir_bblock_t *bblock = scc_ir_ctx_get_bblock(ctx->ir_ctx, bblock_ref);
if (!bblock) {
LOG_ERROR("invalid bblock ref");
return;
}
scc_tree_print_indent(ctx->dump_ctx);
PRINT_NODE(ctx->dump_ctx, "BasicBlock: ");
PRINT_QUOTED_VALUE(ctx->dump_ctx,
bblock->label ? bblock->label : "<unnamed>");
scc_printf("\n");
// 转储基本块中的指令
for (usize i = 0; i < scc_vec_size(bblock->instrs); i++) {
cbool is_last = (i + 1 == scc_vec_size(bblock->instrs));
scc_tree_dump_push_level(ctx->dump_ctx, is_last);
scc_ir_node_ref_t instr_ref = scc_vec_at(bblock->instrs, i);
scc_ir_dump_node(ctx, instr_ref);
scc_tree_dump_pop_level(ctx->dump_ctx);
}
}
// 转储函数
void scc_ir_dump_func(scc_ir_dump_ctx_t *ctx, scc_ir_func_ref_t func_ref) {
scc_ir_func_t *func = scc_ir_ctx_get_func(ctx->ir_ctx, func_ref);
if (!ctx || !func) {
LOG_ERROR("invalid parameter");
return;
}
scc_tree_print_indent(ctx->dump_ctx);
PRINT_NODE(ctx->dump_ctx, "Function: ");
PRINT_QUOTED_VALUE(ctx->dump_ctx, func->name ? func->name : "<unnamed>");
scc_printf("\n");
// 输出函数类型
if (func->type) {
scc_tree_dump_push_level(ctx->dump_ctx, false);
scc_ir_dump_type(ctx, func->type);
scc_tree_dump_pop_level(ctx->dump_ctx);
}
// 输出函数参数
for (usize i = 0; i < scc_vec_size(func->params); i++) {
cbool is_last = (i + 1 == scc_vec_size(func->params));
scc_tree_dump_push_level(ctx->dump_ctx, is_last);
scc_ir_node_ref_t param_ref = scc_vec_at(func->params, i);
scc_ir_dump_node(ctx, param_ref);
scc_tree_dump_pop_level(ctx->dump_ctx);
}
// 输出基本块
for (usize i = 0; i < scc_vec_size(func->bblocks); i++) {
cbool is_last = (i + 1 == scc_vec_size(func->bblocks));
scc_tree_dump_push_level(ctx->dump_ctx, is_last);
scc_ir_bblock_ref_t bblock_ref = scc_vec_at(func->bblocks, i);
scc_ir_dump_bblock(ctx, bblock_ref);
scc_tree_dump_pop_level(ctx->dump_ctx);
}
}
// 转储整个程序
void scc_ir_dump_cprog(scc_ir_dump_ctx_t *ctx) {
// 输出全局值
// if (scc_vec_size(program->global_vals) > 0) {
// print_indented(ctx, "Global Values:", "");
// for (usize i = 0; i < scc_vec_size(program->global_vals); i++) {
// cbool is_last = (i + 1 ==
// scc_vec_size(program->global_vals));
// scc_tree_dump_push_level(ctx->dump_ctx, is_last);
// scc_ir_node_ref_t global_ref =
// scc_vec_at(program->global_vals, i); scc_ir_node_t
// *global_node =
// scc_ir_ctx_get_node(ir_ctx, global_ref);
// if (global_node) {
// scc_ir_dump_node(ctx, ir_ctx, global_node);
// }
// scc_tree_dump_pop_level(ctx->dump_ctx);
// }
// }
// // 输出函数定义
// if (scc_vec_size(ir_ctx->funcs) > 0) {
// print_indented(ctx, "Functions:", "");
// for (usize i = 0; i < scc_vec_size(ir_ctx->funcs); i++) {
// cbool is_last = (i + 1 == scc_vec_size(ir_ctx->funcs));
// scc_tree_dump_push_level(ctx->dump_ctx, is_last);
// scc_ir_func_t func_ref = scc_vec_at(ir_ctx->funcs, i);
// if (func_ref.type != 0) {
// // TODO hack it
// dump_func_ref(ir_ctx, ctx, i + 1);
// }
// scc_tree_dump_pop_level(ctx->dump_ctx);
// }
// }
PRINT_NODE(ctx->dump_ctx, "Func defs:\n");
scc_vec_foreach(ctx->cprog->func_defs, i) {
cbool is_last = (i + 1 == scc_vec_size(ctx->cprog->func_defs));
scc_tree_dump_push_level(ctx->dump_ctx, is_last);
scc_ir_dump_func(ctx, scc_vec_at(ctx->cprog->func_defs, i));
scc_tree_dump_pop_level(ctx->dump_ctx);
}
}
void scc_ir_node_dump(scc_ir_dump_ctx_t *ctx, scc_ir_node_t *in) { return; }
void scc_ir_cprog_dump(scc_ir_dump_ctx_t *ctx, ir_cprog_t *in) { return; }

View File

@@ -6,17 +6,21 @@
typedef enum scc_cstd {
SCC_CSTD_C89,
SCC_CSTD_C99,
SCC_CEXT_ASM,
SCC_CEXT_SCC,
} scc_cstd_t;
/* clang-format off */
// WARNING: Using Binary Search To Fast Find Keyword
// 你必须确保其中是按照字典序排列
#define SCC_CKEYWORD_TABLE \
X(asm , SCC_TOK_SUBTYPE_KEYWORD , SCC_TOK_ASM , SCC_CEXT_ASM) \
X(asm , SCC_TOK_SUBTYPE_KEYWORD , SCC_TOK_ASM , SCC_CEXT_SCC) \
X(atomic , SCC_TOK_SUBTYPE_KEYWORD , SCC_TOK_ATOMIC , SCC_CEXT_SCC) \
X(auto , SCC_TOK_SUBTYPE_KEYWORD , SCC_TOK_AUTO , SCC_CEXT_SCC) \
X(bool , SCC_TOK_SUBTYPE_KEYWORD , SCC_TOK_BOOL , SCC_CEXT_SCC) \
X(break , SCC_TOK_SUBTYPE_KEYWORD , SCC_TOK_BREAK , SCC_CSTD_C89) \
X(case , SCC_TOK_SUBTYPE_KEYWORD , SCC_TOK_CASE , SCC_CSTD_C89) \
X(char , SCC_TOK_SUBTYPE_KEYWORD , SCC_TOK_CHAR , SCC_CSTD_C89) \
X(complex , SCC_TOK_SUBTYPE_KEYWORD , SCC_TOK_COMPLEX , SCC_CEXT_SCC) \
X(const , SCC_TOK_SUBTYPE_KEYWORD , SCC_TOK_CONST , SCC_CSTD_C89) \
X(continue , SCC_TOK_SUBTYPE_KEYWORD , SCC_TOK_CONTINUE , SCC_CSTD_C89) \
X(default , SCC_TOK_SUBTYPE_KEYWORD , SCC_TOK_DEFAULT , SCC_CSTD_C89) \
@@ -148,13 +152,4 @@ static inline cbool scc_lexer_tok_match(const scc_lexer_tok_t *tok,
return tok->type == type;
}
static inline cbool scc_lexer_tok_expect(const scc_lexer_tok_t *tok,
scc_tok_type_t type) {
if (!scc_lexer_tok_match(tok, type)) {
LOG_ERROR("expected token %d, got %d\n", type, tok->type);
return false;
}
return true;
}
#endif /* __SCC_LEXER_TOKEN_H__ */

View File

@@ -92,7 +92,7 @@ static void parse_line(scc_lexer_t *lexer, scc_lexer_tok_t *token) {
if (scc_probe_stream_consume(stream) != ' ') {
scc_lex_parse_skip_line(stream, &lexer->pos);
token->loc.line = token->value.n;
token->loc.line = token->value.u;
}
if (scc_probe_stream_next(stream) != '"') {
@@ -331,6 +331,7 @@ void scc_lexer_get_token(scc_lexer_t *lexer, scc_lexer_tok_t *token) {
break;
case '\r':
case '\n':
scc_probe_stream_back(stream);
scc_lex_parse_skip_endline(stream, &lexer->pos);
scc_probe_stream_sync(stream);
token->type = SCC_TOK_BLANK;
@@ -384,7 +385,7 @@ void scc_lexer_get_token(scc_lexer_t *lexer, scc_lexer_tok_t *token) {
scc_probe_stream_reset(stream);
if (scc_lex_parse_number(stream, &lexer->pos, &output) == true) {
scc_probe_stream_sync(stream);
token->value.n = output;
token->value.u = output;
} else {
LEX_ERROR("Unexpected number literal");
token->type = SCC_TOK_UNKNOWN;

View File

@@ -14,6 +14,7 @@ static void lexer_stream_extend(scc_lexer_stream_t *stream, usize n) {
scc_realloc(null, new_cap * sizeof(scc_lexer_tok_t));
if (!new_data) {
LOG_FATAL("lexer_stream_extend: realloc failed\n");
return;
}
// 将旧缓冲区中的数据拷贝到新缓冲区,保持顺序

10
libs/parser/cbuild.toml Normal file
View File

@@ -0,0 +1,10 @@
[package]
name = "scc_parser"
version = "0.1.0"
dependencies = [
{ name = "scc_core", path = "../../runtime/scc_core" },
{ name = "scc_utils", path = "../../runtime/scc_utils" },
{ name = "lexer", path = "../lexer" },
{ name = "ast", path = "../ast" },
]

View File

@@ -0,0 +1,113 @@
/**
* @file parser.h
*/
#ifndef __SCC_PARSER_H__
#define __SCC_PARSER_H__
#include "scc_ast.h"
#include <lexer.h>
/**
* @brief 解析器状态
*/
typedef struct scc_parser {
scc_lexer_stream_t *lex_stream; // 词法分析器
scc_sema_callbacks_t sema_callbacks; // 语义分析回调
scc_ast_translation_unit_t *translation_unit; // 翻译单元(根节点)
cbool has_error; // 是否有错误
} scc_parser_t;
/**
* @brief 检查当前 token 类型
*/
static inline cbool scc_parse_is(scc_lexer_stream_t *stream,
scc_tok_type_t type) {
const scc_lexer_tok_t *tok = scc_lexer_stream_current(stream);
return tok->type == type;
}
/**
* @brief 检查前瞻 token 类型
*/
static inline cbool scc_parse_peek_is(scc_lexer_stream_t *stream, usize n,
scc_tok_type_t type) {
const scc_lexer_tok_t *tok = scc_lexer_stream_peek(stream, n);
return tok->type == type;
}
/**
* @brief 如果当前 token 匹配则消费
*/
static inline cbool scc_parse_consume_if(scc_lexer_stream_t *stream,
scc_tok_type_t type) {
if (scc_parse_is(stream, type)) {
scc_lexer_stream_consume(stream);
return true;
}
return false;
}
/**
* @brief 消费当前 token 并返回它
*/
static inline const scc_lexer_tok_t *
scc_parse_consume(scc_lexer_stream_t *stream) {
const scc_lexer_tok_t *tok = scc_lexer_stream_current(stream);
scc_lexer_stream_consume(stream);
return tok;
}
/**
* @brief 初始化解析器
* @param parser 解析器实例
* @param lexer 词法分析器实例
* @param callbacks 语义分析回调(可为 null)
*/
void scc_parser_init(scc_parser_t *parser, scc_lexer_stream_t *lexer,
scc_sema_callbacks_t *callbacks);
/**
* @brief 销毁解析器
* @param parser 解析器实例
*/
void scc_parser_drop(scc_parser_t *parser);
/**
* @brief 解析整个翻译单元
* @param parser 解析器实例
* @return 翻译单元 AST 节点
*/
scc_ast_translation_unit_t *scc_parse_translation_unit(scc_parser_t *parser);
/**
* @brief 解析声明
* @param parser 解析器实例
* @return 声明 AST 节点
*/
scc_ast_decl_t *scc_parse_declaration(scc_parser_t *parser);
/**
* @brief 解析语句
* @param parser 解析器实例
* @return 语句 AST 节点
*/
scc_ast_stmt_t *scc_parse_statement(scc_parser_t *parser);
/**
* @brief 解析表达式
* @param parser 解析器实例
* @return 表达式 AST 节点
*/
scc_ast_expr_t *scc_parse_expression(scc_parser_t *parser);
/**
* @brief 解析类型
* @param parser 解析器实例
* @return 类型 AST 节点
*/
scc_ast_type_t *scc_parse_type(scc_parser_t *parser);
cbool scc_parse_is_declaration_start(scc_parser_t *parser, usize offset);
#endif /* __SCC_PARSER_H__ */

View File

@@ -0,0 +1,250 @@
#include <parser.h>
/*
A.2.2 Declarations
(6.7) declaration:
declaration-specifiers init-declarator-list(opt) ;
(6.7) declaration-specifiers:
storage-class-specifier declaration-specifiers(opt)
type-specifier declaration-specifiers(opt)
type-qualifier declaration-specifiers(opt)
function-specifier declaration-specifiers(opt)
(6.7) init-declarator-list:
init-declarator
init-declarator-list , init-declarator
(6.7) init-declarator:
declarator
declarator = initializer
(6.7.1) storage-class-specifier:
typedef
extern
static
auto
register
(6.7.2) type-specifier:
void
char
short
int
long
float
double
signed
unsigned
_Bool
_Complex
struct-or-union-specifier
enum-specifier
typedef-name
(6.7.2.1) struct-or-union-specifier:
struct-or-union identifier(opt) { struct-declaration-list }
struct-or-union identifier
(6.7.2.1) struct-or-union:
struct
union
(6.7.2.1) struct-declaration-list:
struct-declaration
struct-declaration-list struct-declaration
(6.7.2.1) struct-declaration:
specifier-qualifier-list struct-declarator-list ;
(6.7.2.1) specifier-qualifier-list:
type-specifier specifier-qualifier-list(opt)
type-qualifier specifier-qualifier-list(opt)
(6.7.2.1) struct-declarator-list:
struct-declarator
struct-declarator-list , struct-declarator
(6.7.2.1) struct-declarator:
declarator
declarator(opt) : constant-expression
(6.7.2.2) enum-specifier:
enum identifier(opt) { enumerator-list }
enum identifier(opt) { enumerator-list ,}
enum identifier
(6.7.2.2) enumerator-list:
enumerator
enumerator-list , enumerator
(6.7.2.2) enumerator:
enumeration-constant
enumeration-constant = constant-expression
(6.7.3) type-qualifier:
const
restrict
volatile
(6.7.4) function-specifier:
inline
(6.7.5) declarator:
pointer(opt) direct-declarator
(6.7.5) direct-declarator:
identifier
( declarator )
direct-declarator [ type-qualifier-list(opt)
assignment-expression(opt) ]
direct-declarator [ static type-qualifier-list(opt)
assignment-expression ]
direct-declarator [ type-qualifier-list static
assignment-expression ]
direct-declarator [ type-qualifier-list(opt) *]
direct-declarator ( parameter-type-list )
direct-declarator ( identifier-list(opt) )
(6.7.5) pointer:
* type-qualifier-list(opt)
* type-qualifier-list(opt) pointer
(6.7.5) type-qualifier-list:
type-qualifier
type-qualifier-list type-qualifier
(6.7.5) parameter-type-list:
parameter-list
parameter-list , ...
(6.7.5) parameter-list:
parameter-declaration
parameter-list , parameter-declaration
(6.7.5) parameter-declaration:
declaration-specifiers declarator
declaration-specifiers abstract-declarator(opt)
(6.7.5) identifier-list:
identifier
identifier-list , identifier
(6.7.6) type-name:
specifier-qualifier-list abstract-declarator(opt)
(6.7.6) abstract-declarator:
pointer
pointer(opt) direct-abstract-declarator
(6.7.6) direct-abstract-declarator:
( abstract-declarator )
direct-abstract-declarator(opt) [ type-qualifier-list (opt)
assignment-expression(opt) ]
direct-abstract-declarator(opt) [static type-qualifier-list(opt)
assignment-expression ]
direct-abstract-declaratoropt [ type-qualifier-list static
assignment-expression ]
direct-abstract-declarator(opt) [ * ]
direct-abstract-declarator(opt) ( parameter-type-list(opt) )
(6.7.7) typedef-name:
identifier
(6.7.8) initializer:
assignment-expression
{ initializer-list }
{ initializer-list , }
(6.7.8) initializer-list:
designation(opt) initializer
initializer-list , designation(opt) initializer
(6.7.8) designation:
designator-list =
(6.7.8) designator-list:
designator
designator-list designator
(6.7.8) designator:
[ constant-expression ]
. identifier
A.2.4 External definitions
(6.9) translation-unit:
external-declaration
translation-unit external-declaration
(6.9) external-declaration:
function-definition
declaration
(6.9.1) function-definition:
declaration-specifiers declarator declaration-list(opt)
compound-statement
(6.9.1) declaration-list:
declaration
declaration-list declaration
*/
scc_ast_decl_t *scc_parse_declaration(scc_parser_t *parser) {
/**
* ISO/IEC 9899:TC3
* 6.7 Declarations
* Syntax
*
* declaration:
* declaration-specifiers init-declarator-list(opt) ;
* declaration-specifiers:
* storage-class-specifier declaration-specifiers(opt)
* type-specifier declaration-specifiers(opt)
* type-qualifier declaration-specifiers(opt)
* function-specifier declaration-specifiers(opt)
* init-declarator-list:
* init-declarator
* init-declarator-list , init-declarator
* init-declarator:
* declarator
* declarator = initializer
*/
if (!scc_parse_is_declaration_start(parser, 0)) {
return null;
}
scc_ast_type_t *type = scc_parse_type(parser);
if (type == null) {
LOG_ERROR("Failed to parse type");
return null;
}
const scc_lexer_tok_t *tok = scc_lexer_stream_current(parser->lex_stream);
if (!scc_lexer_tok_match(tok, SCC_TOK_IDENT)) {
LOG_ERROR("Expected identifier, got %s", scc_get_tok_name(tok->type));
return null;
}
scc_lexer_stream_consume(parser->lex_stream);
scc_ast_decl_t *decl = scc_malloc(sizeof(scc_ast_decl_t));
/*
(6.7.5) declarator:
pointeropt direct-declarator
(6.7.5) direct-declarator:
identifier
( declarator )
direct-declarator [ type-qualifier-listopt assignment-expressionopt ]
direct-declarator [static type-qualifier-listopt assignment-expression ]
direct-declarator [ type-qualifier-list static assignment-expression ]
direct-declarator [ type-qualifier-listopt *]
direct-declarator ( parameter-type-list )
direct-declarator ( identifier-listopt )
*/
if (!scc_parse_consume_if(parser->lex_stream, SCC_TOK_L_PAREN)) {
// TODO
if (scc_parse_consume_if(parser->lex_stream, SCC_TOK_SEMICOLON)) {
decl->base.type = SCC_AST_DECL_VAR;
decl->var.type = type;
decl->var.name = tok->value.cstr.data;
decl->var.init = null;
return decl;
} else if (scc_parse_consume_if(parser->lex_stream, SCC_TOK_ASSIGN)) {
decl->base.type = SCC_AST_DECL_VAR;
decl->var.type = type;
decl->var.name = tok->value.cstr.data;
decl->var.init = scc_parse_expression(parser);
return decl;
}
return null;
}
// function decl
decl->base.type = SCC_AST_DECL_FUNC;
decl->func.name = tok->value.cstr.data;
decl->func.type = scc_malloc(sizeof(scc_ast_type_t));
decl->func.type->base.type = SCC_AST_TYPE_FUNCTION;
scc_vec_init(decl->func.type->function.param_types);
decl->func.type->function.return_type = type;
// TODO
decl->func.type->function.is_variadic = false;
// TODO param type
scc_parse_consume_if(parser->lex_stream, SCC_TOK_VOID);
if (!scc_parse_consume_if(parser->lex_stream, SCC_TOK_R_PAREN)) {
return null;
}
if (!scc_parse_is(parser->lex_stream, SCC_TOK_L_BRACE)) {
return null;
}
decl->func.body = scc_parse_statement(parser);
Assert(decl->func.type != null);
Assert(decl->func.type->base.type == SCC_AST_TYPE_FUNCTION);
Assert(decl->func.body != null);
Assert(decl->func.body->base.type == SCC_AST_STMT_COMPOUND);
return decl;
}

View File

@@ -0,0 +1,918 @@
/**
* @file parse_expr.c
* @author your name (you@domain.com)
* @brief Pratt Parser表达式解析器
* @version 0.1
* @date 2026-01-09
*
* @copyright Copyright (c) 2026
*
*/
#include <parser.h>
/*
A.2.1 Expressions
(6.5.1)
primary-expression:
identifier
constant
string-literal
( expression )
(6.5.2)
postfix-expression:
primary-expression
postfix-expression [ expression ]
postfix-expression ( argument-expression-list(opt) )
postfix-expression . identifier
postfix-expression -> identifier
postfix-expression ++
postfix-expression --
( type-name ) { initializer-list }
( type-name ) { initializer-list , }
(6.5.2)
argument-expression-list:
assignment-expression
argument-expression-list , assignment-expression
(6.5.3)
unary-expression:
postfix-expression
++ unary-expression
-- unary-expression
unary-operator cast-expression
sizeof unary-expression
sizeof ( type-name )
(6.5.3)
unary-operator: one of
& * + - ~ !
(6.5.4)
cast-expression:
unary-expression
( type-name ) cast-expression
(6.5.5)
multiplicative-expression:
cast-expression
multiplicative-expression * cast-expression
multiplicative-expression / cast-expression
multiplicative-expression % cast-expression
(6.5.6)
additive-expression:
multiplicative-expression
additive-expression + multiplicative-expression
additive-expression - multiplicative-expression
(6.5.7)
shift-expression:
additive-expression
shift-expression << additive-expression
shift-expression >> additive-expression
(6.5.8)
relational-expression:
shift-expression
relational-expression < shift-expression
relational-expression > shift-expression
relational-expression <= shift-expression
relational-expression >= shift-expression
(6.5.9)
equality-expression:
relational-expression
equality-expression == relational-expression
equality-expression != relational-expression
(6.5.10)
AND-expression:
equality-expression
AND-expression & equality-expression
(6.5.11)
exclusive-OR-expression:
AND-expression
exclusive-OR-expression ^ AND-expression
(6.5.12)
inclusive-OR-expression:
exclusive-OR-expression
inclusive-OR-expression | exclusive-OR-expression
(6.5.13)
logical-AND-expression:
inclusive-OR-expression
logical-AND-expression && inclusive-OR-expression
(6.5.14)
logical-OR-expression:
logical-AND-expression
logical-OR-expression || logical-AND-expression
(6.5.15)
conditional-expression:
logical-OR-expression
logical-OR-expression ? expression : conditional-expression
(6.5.16)
assignment-expression:
conditional-expression
unary-expression assignment-operator assignment-expression
(6.5.16)
assignment-operator: one of
= *= /= %= +=-= <<= >>= &= ^= |=
(6.5.17)
expression:
assignment-expression
expression , assignment-expression
(6.6)
constant-expression:
conditional-expression
*/
/**
* @brief 从token映射到AST操作符
* @param tok_type 词法token类型
* @param is_unary 是否为一元操作符上下文
* @return AST操作符类型
*/
static scc_ast_expr_op_t scc_ast_token_to_operator(scc_tok_type_t tok_type,
cbool is_unary) {
switch (tok_type) {
/* 赋值操作符 */
case SCC_TOK_ASSIGN:
return SCC_AST_OP_ASSIGN;
case SCC_TOK_ASSIGN_ADD:
return SCC_AST_OP_ASSIGN_ADD;
case SCC_TOK_ASSIGN_SUB:
return SCC_AST_OP_ASSIGN_SUB;
case SCC_TOK_ASSIGN_MUL:
return SCC_AST_OP_ASSIGN_MUL;
case SCC_TOK_ASSIGN_DIV:
return SCC_AST_OP_ASSIGN_DIV;
case SCC_TOK_ASSIGN_MOD:
return SCC_AST_OP_ASSIGN_MOD;
case SCC_TOK_ASSIGN_AND:
return SCC_AST_OP_ASSIGN_AND;
case SCC_TOK_ASSIGN_XOR:
return SCC_AST_OP_ASSIGN_XOR;
case SCC_TOK_ASSIGN_OR:
return SCC_AST_OP_ASSIGN_OR;
case SCC_TOK_ASSIGN_L_SH:
return SCC_AST_OP_ASSIGN_LSHIFT;
case SCC_TOK_ASSIGN_R_SH:
return SCC_AST_OP_ASSIGN_RSHIFT;
/* 逻辑操作符 */
case SCC_TOK_OR_OR:
return SCC_AST_OP_LOGICAL_OR;
case SCC_TOK_AND_AND:
return SCC_AST_OP_LOGICAL_AND;
/* 位操作符 */
case SCC_TOK_OR:
return SCC_AST_OP_BITWISE_OR;
case SCC_TOK_XOR:
return SCC_AST_OP_BITWISE_XOR;
case SCC_TOK_AND:
return is_unary ? SCC_AST_OP_ADDRESS_OF : SCC_AST_OP_BITWISE_AND;
/* 相等性操作符 */
case SCC_TOK_EQ:
return SCC_AST_OP_EQUAL;
case SCC_TOK_NEQ:
return SCC_AST_OP_NOT_EQUAL;
/* 关系操作符 */
case SCC_TOK_LT:
return SCC_AST_OP_LESS;
case SCC_TOK_GT:
return SCC_AST_OP_GREATER;
case SCC_TOK_LE:
return SCC_AST_OP_LESS_EQUAL;
case SCC_TOK_GE:
return SCC_AST_OP_GREATER_EQUAL;
/* 移位操作符 */
case SCC_TOK_L_SH:
return SCC_AST_OP_LEFT_SHIFT;
case SCC_TOK_R_SH:
return SCC_AST_OP_RIGHT_SHIFT;
/* 算术操作符 */
case SCC_TOK_ADD:
return is_unary ? SCC_AST_OP_UNARY_PLUS : SCC_AST_OP_ADD;
case SCC_TOK_SUB:
return is_unary ? SCC_AST_OP_UNARY_MINUS : SCC_AST_OP_SUB;
case SCC_TOK_MUL:
return is_unary ? SCC_AST_OP_INDIRECTION : SCC_AST_OP_MUL;
case SCC_TOK_DIV:
return SCC_AST_OP_DIV;
case SCC_TOK_MOD:
return SCC_AST_OP_MOD;
/* 一元操作符 */
case SCC_TOK_NOT:
return SCC_AST_OP_LOGICAL_NOT;
case SCC_TOK_BIT_NOT:
return SCC_AST_OP_BITWISE_NOT;
case SCC_TOK_ADD_ADD:
return is_unary ? SCC_AST_OP_PREFIX_INCREMENT
: SCC_AST_OP_POSTFIX_INCREMENT;
case SCC_TOK_SUB_SUB:
return is_unary ? SCC_AST_OP_PREFIX_DECREMENT
: SCC_AST_OP_POSTFIX_DECREMENT;
default:
return SCC_AST_OP_NONE;
}
}
/**
* @brief 运算符优先级定义
*/
typedef enum {
PREC_NONE = 0, // 无优先级
PREC_COMMA = 1, // ,
PREC_ASSIGNMENT = 2, // = += -= *= /= %= &= ^= |= <<= >>=
PREC_CONDITIONAL = 3, // ?:
PREC_LOGICAL_OR = 4, // ||
PREC_LOGICAL_AND = 5, // &&
PREC_BITWISE_OR = 6, // |
PREC_BITWISE_XOR = 7, // ^
PREC_BITWISE_AND = 8, // &
PREC_EQUALITY = 9, // == !=
PREC_RELATIONAL = 10, // < > <= >=
PREC_SHIFT = 11, // << >>
PREC_ADDITIVE = 12, // + -
PREC_MULTIPLICATIVE = 13, // * / %
PREC_CAST = 14, // 类型转换
PREC_UNARY = 15, // ++ -- + - * & ~ ! sizeof
PREC_POSTFIX = 16, // [] () . -> ++ --
PREC_PRIMARY = 17, // 最高优先级
} scc_precedence_t;
/**
* @brief 获取二元运算符优先级
*/
static scc_precedence_t get_binary_precedence(scc_tok_type_t op) {
switch (op) {
case SCC_TOK_COMMA:
return PREC_COMMA;
case SCC_TOK_ASSIGN:
case SCC_TOK_ASSIGN_ADD:
case SCC_TOK_ASSIGN_SUB:
case SCC_TOK_ASSIGN_MUL:
case SCC_TOK_ASSIGN_DIV:
case SCC_TOK_ASSIGN_MOD:
case SCC_TOK_ASSIGN_AND:
case SCC_TOK_ASSIGN_XOR:
case SCC_TOK_ASSIGN_OR:
case SCC_TOK_ASSIGN_L_SH:
case SCC_TOK_ASSIGN_R_SH:
return PREC_ASSIGNMENT;
case SCC_TOK_COND:
return PREC_CONDITIONAL;
case SCC_TOK_OR_OR:
return PREC_LOGICAL_OR;
case SCC_TOK_AND_AND:
return PREC_LOGICAL_AND;
case SCC_TOK_OR:
return PREC_BITWISE_OR;
case SCC_TOK_XOR:
return PREC_BITWISE_XOR;
case SCC_TOK_AND:
return PREC_BITWISE_AND;
case SCC_TOK_EQ:
case SCC_TOK_NEQ:
return PREC_EQUALITY;
case SCC_TOK_LT:
case SCC_TOK_GT:
case SCC_TOK_LE:
case SCC_TOK_GE:
return PREC_RELATIONAL;
case SCC_TOK_L_SH:
case SCC_TOK_R_SH:
return PREC_SHIFT;
case SCC_TOK_ADD:
case SCC_TOK_SUB:
return PREC_ADDITIVE;
case SCC_TOK_MUL:
case SCC_TOK_DIV:
case SCC_TOK_MOD:
return PREC_MULTIPLICATIVE;
default:
return PREC_NONE;
}
}
/**
* @brief 检查是否是赋值运算符
*/
static cbool is_assignment_operator(scc_tok_type_t op) {
switch (op) {
case SCC_TOK_ASSIGN:
case SCC_TOK_ASSIGN_ADD:
case SCC_TOK_ASSIGN_SUB:
case SCC_TOK_ASSIGN_MUL:
case SCC_TOK_ASSIGN_DIV:
case SCC_TOK_ASSIGN_MOD:
case SCC_TOK_ASSIGN_AND:
case SCC_TOK_ASSIGN_XOR:
case SCC_TOK_ASSIGN_OR:
case SCC_TOK_ASSIGN_L_SH:
case SCC_TOK_ASSIGN_R_SH:
return true;
default:
return false;
}
}
/**
* @brief 检查是否是二元运算符
*/
static cbool is_binary_operator(scc_tok_type_t op) {
return get_binary_precedence(op) != PREC_NONE;
}
static inline scc_ast_expr_t *expr_create(scc_parser_t *parser,
scc_ast_node_type_t type) {
scc_ast_expr_t *expr = (scc_ast_expr_t *)scc_malloc(sizeof(scc_ast_expr_t));
Assert(expr != null);
expr->base.type = type;
expr->base.loc = scc_pos_create();
return expr;
}
/**
* @brief 解析基本表达式
*
* (6.5.1) primary-expression:
* identifier
* constant
* string-literal
* ( expression )
*/
static scc_ast_expr_t *parse_primary_expression(scc_parser_t *parser) {
const scc_lexer_tok_t *tok = scc_lexer_stream_current(parser->lex_stream);
switch (tok->type) {
case SCC_TOK_IDENT: {
scc_ast_expr_t *expr = expr_create(parser, SCC_AST_EXPR_IDENTIFIER);
if (!expr)
return null;
expr->identifier.name = tok->value.cstr.data;
scc_lexer_stream_consume(parser->lex_stream);
// 调用语义回调
if (parser->sema_callbacks.on_expr) {
parser->sema_callbacks.on_expr(parser->sema_callbacks.context,
expr->base.type, expr);
}
return expr;
}
case SCC_TOK_INT_LITERAL:
case SCC_TOK_FLOAT_LITERAL:
case SCC_TOK_CHAR_LITERAL: {
scc_ast_expr_t *expr = expr_create(parser, SCC_AST_EXPR_INT_LITERAL);
if (!expr)
return null;
expr->literal.value = tok->value;
scc_lexer_stream_consume(parser->lex_stream);
if (parser->sema_callbacks.on_expr) {
parser->sema_callbacks.on_expr(parser->sema_callbacks.context,
expr->base.type, expr);
}
return expr;
}
case SCC_TOK_STRING_LITERAL: {
scc_ast_expr_t *expr = expr_create(parser, SCC_AST_EXPR_STRING_LITERAL);
if (!expr)
return null;
expr->literal.value = tok->value;
scc_lexer_stream_consume(parser->lex_stream);
if (parser->sema_callbacks.on_expr) {
parser->sema_callbacks.on_expr(parser->sema_callbacks.context,
expr->base.type, expr);
}
return expr;
}
case SCC_TOK_L_PAREN: {
TODO();
// // 保存当前位置,用于区分类型转换和括号表达式
// usize save_pos = parser->lex_stream->curr_pos;
// // 跳过 '('
// scc_lexer_stream_consume(parser->lex_stream);
// // 尝试解析类型转换
// if (parser_is_type_start(parser)) {
// scc_ast_type_t *type = scc_parse_type_name(parser);
// if (type && parser_consume_if(parser, SCC_TOK_R_PAREN)) {
// // 成功解析类型转换
// scc_ast_expr_t *cast = expr_create(parser,
// SCC_AST_EXPR_CAST); if (!cast) {
// scc_free(type);
// return null;
// }
// cast->cast.type = type;
// cast->cast.expr = scc_parse_expression(parser, 0); //
// 递归解析
// if (parser->sema_callbacks.on_expr) {
// parser->sema_callbacks.on_expr(
// parser->sema_callbacks.context, cast->node_type,
// cast);
// }
// return cast;
// }
// // 解析失败,清理
// if (type)
// scc_free(type);
// }
// // 不是类型转换,恢复为括号表达式
// parser->lex_stream->curr_pos = save_pos;
// scc_lexer_stream_consume(parser->lex_stream); // 跳过 '('
// scc_ast_expr_t *expr = scc_parse_expression(parser, 0);
// if (!expr) {
// return null;
// }
// if (!parser_consume_if(parser, SCC_TOK_R_PAREN)) {
// PARSER_ERROR(parser, "expected ')' after expression");
// scc_free(expr);
// return null;
// }
// 括号表达式不需要特殊节点,直接返回内部表达式
// return expr;
}
default:
LOG_ERROR("expected primary expression, got %s",
scc_get_tok_name(tok->type));
return null;
}
}
/**
* @brief 解析后缀表达式
*
* (6.5.2) postfix-expression:
* primary-expression
* postfix-expression [ expression ]
* postfix-expression ( argument-expression-list(opt) )
* postfix-expression . identifier
* postfix-expression -> identifier
* postfix-expression ++
* postfix-expression --
* ( type-name ) { initializer-list }
* ( type-name ) { initializer-list , }
*/
static scc_ast_expr_t *parse_postfix_expression(scc_parser_t *parser,
scc_ast_expr_t *lhs) {
scc_ast_expr_t *expr = lhs;
while (true) {
const scc_lexer_tok_t *tok =
scc_lexer_stream_current(parser->lex_stream);
switch (tok->type) {
case SCC_TOK_L_BRACKET: { // 数组下标
scc_lexer_stream_consume(parser->lex_stream); // 跳过 '['
scc_ast_expr_t *subscript =
expr_create(parser, SCC_AST_EXPR_ARRAY_SUBSCRIPT);
if (!subscript) {
scc_free(expr);
return null;
}
subscript->subscript.array = expr;
subscript->subscript.index = scc_parse_expression(parser);
if (!subscript->subscript.index) {
scc_free(subscript);
return null;
}
if (!scc_parse_consume_if(parser->lex_stream, SCC_TOK_R_BRACKET)) {
LOG_ERROR("expected ']' after array index");
scc_free(subscript);
return null;
}
expr = subscript;
break;
}
case SCC_TOK_L_PAREN: { // 函数调用
scc_lexer_stream_consume(parser->lex_stream); // 跳过 '('
scc_ast_expr_t *call = expr_create(parser, SCC_AST_EXPR_CALL);
if (!call) {
scc_free(expr);
return null;
}
call->call.callee = expr;
scc_vec_init(call->call.args);
// 解析参数列表
if (!scc_parse_is(parser->lex_stream, SCC_TOK_R_PAREN)) {
do {
scc_ast_expr_t *arg = scc_parse_expression(parser);
if (!arg) {
// 清理已解析的参数
scc_vec_foreach(call->call.args, i) {
scc_free(scc_vec_at(call->call.args, i));
}
scc_vec_free(call->call.args);
scc_free(call);
return null;
}
scc_vec_push(call->call.args, arg);
if (!scc_parse_consume_if(parser->lex_stream,
SCC_TOK_COMMA)) {
break;
}
} while (true);
}
if (!scc_parse_consume_if(parser->lex_stream, SCC_TOK_R_PAREN)) {
LOG_ERROR("expected ')' after argument list");
// 清理
scc_vec_foreach(call->call.args, i) {
scc_free(scc_vec_at(call->call.args, i));
}
scc_vec_free(call->call.args);
scc_free(call);
return null;
}
expr = call;
break;
}
case SCC_TOK_DOT: { // 成员访问
scc_lexer_stream_consume(parser->lex_stream); // 跳过 '.'
scc_ast_expr_t *member = expr_create(parser, SCC_AST_EXPR_MEMBER);
if (!member) {
scc_free(expr);
return null;
}
member->member.base = expr;
if (!scc_parse_is(parser->lex_stream, SCC_TOK_IDENT)) {
LOG_ERROR("expected identifier after '.'");
scc_free(member);
return null;
}
member->member.member_name = tok->value.cstr.data;
scc_lexer_stream_consume(parser->lex_stream); // 跳过标识符
expr = member;
break;
}
case SCC_TOK_DEREF: { // 指针成员访问 ->
scc_lexer_stream_consume(parser->lex_stream); // 跳过 '->'
scc_ast_expr_t *ptr_member =
expr_create(parser, SCC_AST_EXPR_PTR_MEMBER);
if (!ptr_member) {
scc_free(expr);
return null;
}
ptr_member->ptr_member.base = expr;
if (!scc_parse_is(parser->lex_stream, SCC_TOK_IDENT)) {
LOG_ERROR("expected identifier after '->'");
scc_free(ptr_member);
return null;
}
ptr_member->ptr_member.member_name = tok->value.cstr.data;
scc_lexer_stream_consume(parser->lex_stream); // 跳过标识符
expr = ptr_member;
break;
}
case SCC_TOK_ADD_ADD: // 后缀++
case SCC_TOK_SUB_SUB: { // 后缀--
// 跳过操作符
scc_lexer_stream_consume(parser->lex_stream);
scc_ast_expr_t *unary = expr_create(parser, SCC_AST_EXPR_UNARY);
if (!unary) {
scc_free(expr);
return null;
}
unary->unary.op = scc_ast_token_to_operator(tok->type, false);
unary->unary.operand = expr;
expr = unary;
break;
}
default:
// 不是后缀操作符,返回当前表达式
return expr;
}
// 调用语义回调
// if (parser->sema_callbacks.on_expr) {
// parser->sema_callbacks.on_expr(parser->sema_callbacks.context,
// expr->base.type, expr);
// }
}
}
/**
* @brief 解析一元表达式
*
* (6.5.3) unary-expression:
* postfix-expression
* ++ unary-expression
* -- unary-expression
* unary-operator cast-expression
* sizeof unary-expression
* sizeof ( type-name )
*/
static scc_ast_expr_t *parse_unary_expression(scc_parser_t *parser) {
const scc_lexer_tok_t *tok = scc_lexer_stream_current(parser->lex_stream);
switch (tok->type) {
case SCC_TOK_ADD_ADD: // 前缀++
case SCC_TOK_SUB_SUB: { // 前缀--
scc_lexer_stream_consume(parser->lex_stream); // 跳过操作符
scc_ast_expr_t *unary = expr_create(parser, SCC_AST_EXPR_UNARY);
if (!unary)
return null;
unary->unary.op = scc_ast_token_to_operator(tok->type, true);
unary->unary.operand = parse_unary_expression(parser);
if (!unary->unary.operand) {
scc_free(unary);
return null;
}
// if (parser->sema_callbacks.on_expr) {
// parser->sema_callbacks.on_expr(parser->sema_callbacks.context,
// unary->node_type, unary);
// }
return unary;
}
case SCC_TOK_ADD: // +
case SCC_TOK_SUB: // -
case SCC_TOK_MUL: // *
case SCC_TOK_AND: // &
case SCC_TOK_NOT: // !
case SCC_TOK_BIT_NOT: { // ~
// 跳过操作符
scc_lexer_stream_consume(parser->lex_stream);
scc_ast_expr_t *unary = expr_create(parser, SCC_AST_EXPR_UNARY);
if (!unary)
return null;
unary->unary.op = scc_ast_token_to_operator(tok->type, true);
unary->unary.operand = parse_unary_expression(parser);
if (!unary->unary.operand) {
scc_free(unary);
return null;
}
// if (parser->sema_callbacks.on_expr) {
// parser->sema_callbacks.on_expr(parser->sema_callbacks.context,
// unary->node_type, unary);
// }
return unary;
}
case SCC_TOK_SIZEOF: { // sizeof
// scc_lexer_stream_consume(parser->lex_stream); // 跳过 'sizeof'
// scc_ast_expr_t *size_of = expr_create(parser, SCC_AST_EXPR_SIZE_OF);
// if (!size_of)
// return null;
// size_of->size_align.is_size_of = true;
// // 检查是否是 sizeof(type) 或 sizeof expr
// if (scc_parse_consume_if(parser->lex_stream, SCC_TOK_L_PAREN)) {
// // 检查是否是类型
// // if (parser_is_type_start(parser)) {
// // size_of->size_align.type = scc_parse_type_name(parser);
// // if (!size_of->size_align.type) {
// // scc_free(size_of);
// // return null;
// // }
// // } else {
// size_of->size_align.expr = scc_parse_expression(parser);
// if (!size_of->size_align.expr) {
// scc_free(size_of);
// return null;
// }
// // }
// if (!scc_parse_consume_if(parser->lex_stream, SCC_TOK_R_PAREN)) {
// LOG_ERROR("expected ')' after sizeof");
// // if (size_of->size_align.type)
// // scc_free(size_of->size_align.type);
// // if (size_of->size_align.expr)
// // scc_free(size_of->size_align.expr);
// // scc_free(size_of);
// // return null;
// }
// } else {
// size_of->size_align.expr = parse_unary_expression(parser);
// if (!size_of->size_align.expr) {
// scc_free(size_of);
// return null;
// }
// }
// // if (parser->sema_callbacks.on_expr) {
// // parser->sema_callbacks.on_expr(parser->sema_callbacks.context,
// // size_of->node_type, size_of);
// // }
// return size_of;
}
default:
// 不是一元操作符,解析基本表达式
scc_ast_expr_t *primary = parse_primary_expression(parser);
if (!primary)
return null;
// 应用后缀操作符
return parse_postfix_expression(parser, primary);
}
}
/**
* @brief 解析强制转换表达式
*
* (6.5.4) cast-expression:
* unary-expression
* ( type-name ) cast-expression
*/
static scc_ast_expr_t *parse_cast_expression(scc_parser_t *parser) {
// 检查是否是类型转换
// if (parser_is_cast_expression(parser)) {
// // 我们已经知道是 ( type-name ) 格式
// scc_lexer_stream_consume(parser->lex_stream); // 跳过 '('
// scc_ast_type_t *type = scc_parse_type_name(parser);
// if (!type) {
// return null;
// }
// if (!parser_consume_if(parser, SCC_TOK_R_PAREN)) {
// PARSER_ERROR(parser, "expected ')' after type name");
// scc_free(type);
// return null;
// }
// scc_ast_expr_t *cast = expr_create(parser, SCC_AST_EXPR_CAST);
// if (!cast) {
// scc_free(type);
// return null;
// }
// cast->cast.type = type;
// cast->cast.expr = parse_cast_expression(parser); // 递归解析
// if (!cast->cast.expr) {
// scc_free(cast);
// return null;
// }
// if (parser->sema_callbacks.on_expr) {
// parser->sema_callbacks.on_expr(parser->sema_callbacks.context,
// cast->node_type, cast);
// }
// return cast;
// }
// 不是类型转换,解析一元表达式
return parse_unary_expression(parser);
}
/**
* @brief Pratt Parser核心解析表达式
* @param parser 解析器
* @param min_prec 最小优先级
* @return 表达式AST节点
*/
static scc_ast_expr_t *
parse_expression_with_precedence(scc_parser_t *parser,
scc_precedence_t min_prec) {
// 解析左侧表达式(一元表达式或基本表达式)
scc_ast_expr_t *lhs = parse_cast_expression(parser);
if (!lhs) {
return null;
}
while (true) {
const scc_lexer_tok_t *tok =
scc_lexer_stream_current(parser->lex_stream);
scc_tok_type_t op = tok->type;
scc_precedence_t prec = get_binary_precedence(op);
// 检查是否达到最小优先级或不是二元运算符
if (prec < min_prec || prec == PREC_NONE) {
break;
}
// 特殊处理条件表达式 ?:
if (op == SCC_TOK_COND) {
scc_lexer_stream_consume(parser->lex_stream); // 跳过 '?'
scc_ast_expr_t *cond_expr = expr_create(parser, SCC_AST_EXPR_COND);
if (!cond_expr) {
scc_free(lhs);
return null;
}
cond_expr->cond.cond = lhs;
// 解析then表达式
cond_expr->cond.then_expr =
parse_expression_with_precedence(parser, PREC_NONE);
if (!cond_expr->cond.then_expr) {
scc_free(cond_expr);
scc_free(lhs);
return null;
}
// 期望 ':'
if (!scc_parse_consume_if(parser->lex_stream, SCC_TOK_COLON)) {
LOG_ERROR("expected ':' in conditional expression");
scc_free(cond_expr);
scc_free(lhs);
return null;
}
// 解析else表达式条件表达式右结合
cond_expr->cond.else_expr =
parse_expression_with_precedence(parser, PREC_CONDITIONAL - 1);
if (!cond_expr->cond.else_expr) {
scc_free(cond_expr);
scc_free(lhs);
return null;
}
lhs = cond_expr;
continue;
}
// 对于赋值运算符右侧优先级需要减1右结合性
scc_precedence_t next_min_prec;
if (is_assignment_operator(op)) {
next_min_prec = (scc_precedence_t)(prec - 1); // 右结合
} else {
next_min_prec = (scc_precedence_t)(prec + 1); // 左结合
}
scc_lexer_stream_consume(parser->lex_stream); // 跳过操作符
// 解析右侧表达式
scc_ast_expr_t *rhs =
parse_expression_with_precedence(parser, next_min_prec);
if (!rhs) {
scc_free(lhs);
return null;
}
// 创建二元表达式节点
scc_ast_expr_t *binary = expr_create(parser, SCC_AST_EXPR_BINARY);
if (!binary) {
scc_free(lhs);
scc_free(rhs);
return null;
}
binary->binary.op = scc_ast_token_to_operator(op, false);
binary->binary.lhs = lhs;
binary->binary.rhs = rhs;
lhs = binary;
}
// if (parser->sema_callbacks.on_expr) {
// parser->sema_callbacks.on_expr(parser->sema_callbacks.context,
// binary->node_type, binary);
// }
return lhs;
}
scc_ast_expr_t *scc_parse_expression(scc_parser_t *parser) {
return parse_expression_with_precedence(parser, PREC_NONE);
}

View File

@@ -0,0 +1,426 @@
/*
415
ISO/IEC 9899:TC3
Committee Draft — Septermber 7, 2007
WG14/N1256
A.2.3 Statements
(6.8)
statement:
labeled-statement
compound-statement
expression-statement
selection-statement
iteration-statement
jump-statement
(6.8.1)
labeled-statement:
identifier : statement
case constant-expression : statement
default : statement
(6.8.2)
compound-statement:
{ block-item-list(opt) }
(6.8.2)
block-item-list:
block-item
block-item-list block-item
(6.8.2)
block-item:
declaration
statement
(6.8.3)
expression-statement:
expression(opt) ;
(6.8.4)
selection-statement:
if ( expression ) statement
if ( expression ) statement else statement
switch ( expression ) statement
(6.8.5)
iteration-statement:
while ( expression ) statement
do statement while ( expression );
for ( expression(opt) ; expression(opt) ; expression(opt) ) statement
for ( declaration expression(opt) ; expression(opt) ) statement
(6.8.6)
jump-statement:
goto identifier ;
continue ;
break ;
return expression(opt) ;
*/
#include <parser.h>
static inline scc_ast_stmt_t *ast_stmt_alloc() {
scc_ast_stmt_t *stmt = (scc_ast_stmt_t *)scc_malloc(sizeof(scc_ast_stmt_t));
Assert(stmt != null);
stmt->base.type = SCC_AST_TRANSLATION_UNIT;
stmt->base.loc = scc_pos_create();
return stmt;
}
static inline scc_ast_expr_t *ast_parse_paren_expression(scc_parser_t *parser) {
if (!scc_parse_consume_if(parser->lex_stream, SCC_TOK_L_PAREN)) {
LOG_ERROR("Expected '(' before like `( expression )` .");
}
scc_ast_expr_t *ret = scc_parse_expression(parser);
if (!scc_parse_consume_if(parser->lex_stream, SCC_TOK_R_PAREN)) {
LOG_ERROR("Expected ')' after like `( expression )` .");
}
return ret;
}
static scc_ast_stmt_t *parse_label_statement(scc_parser_t *parser) {
const scc_lexer_tok_t *tok = scc_lexer_stream_current(parser->lex_stream);
if (!scc_parse_consume_if(parser->lex_stream, SCC_TOK_IDENT)) {
return null;
}
if (!scc_parse_consume_if(parser->lex_stream, SCC_TOK_COLON)) {
LOG_ERROR("Expected constant expression after case.");
return null;
}
scc_ast_stmt_t *statement = scc_parse_statement(parser);
if (statement == null) {
Panic("expect stmt");
}
scc_ast_stmt_t *stmt = ast_stmt_alloc();
Assert(stmt != null);
stmt->base.type = SCC_AST_STMT_LABEL;
// TODO maybe use cstring
stmt->label_stmt.label = tok->value.cstr.data;
stmt->label_stmt.stmt = statement;
return stmt;
}
static scc_ast_stmt_t *parse_case_statement(scc_parser_t *parser) {
if (!scc_parse_consume_if(parser->lex_stream, SCC_TOK_CASE)) {
return null;
}
scc_ast_expr_t *expr = null;
// TODO = scc_parser_constant_expression();
if (!scc_parse_consume_if(parser->lex_stream, SCC_TOK_COLON)) {
LOG_ERROR("Expected constant expression after case.");
return null;
}
scc_ast_stmt_t *statement = scc_parse_statement(parser);
if (statement == null) {
Panic("expect stmt");
}
scc_ast_stmt_t *stmt = ast_stmt_alloc();
Assert(stmt != null);
stmt->case_stmt.expr = expr;
stmt->base.type = SCC_AST_STMT_CASE;
stmt->case_stmt.stmt = statement;
return stmt;
}
static scc_ast_stmt_t *parse_default_statement(scc_parser_t *parser) {
if (!scc_parse_consume_if(parser->lex_stream, SCC_TOK_DEFAULT)) {
return null;
}
if (!scc_parse_consume_if(parser->lex_stream, SCC_TOK_COLON)) {
LOG_ERROR("Expected constant expression after case.");
return null;
}
scc_ast_stmt_t *statement = scc_parse_statement(parser);
if (statement == null) {
Panic("expect stmt");
}
scc_ast_stmt_t *stmt = ast_stmt_alloc();
Assert(stmt != null);
stmt->base.type = SCC_AST_STMT_DEFAULT;
stmt->default_stmt.stmt = statement;
return stmt;
}
static scc_ast_stmt_t *parse_compound_statement(scc_parser_t *parser) {
if (!scc_parse_consume_if(parser->lex_stream, SCC_TOK_L_BRACE)) {
return null;
}
scc_ast_stmt_t *stmt = ast_stmt_alloc();
stmt->base.type = SCC_AST_STMT_COMPOUND;
scc_vec_init(stmt->compound.block_items);
while (!scc_parse_consume_if(parser->lex_stream, SCC_TOK_R_BRACE)) {
/// TODO
// scc_parse_is_decl();
scc_ast_node_type_t *ret = null;
ret = (scc_ast_node_type_t *)scc_parse_declaration(parser);
if (ret == null) {
ret = (scc_ast_node_type_t *)scc_parse_statement(parser);
}
if (ret == null) {
LOG_ERROR("Invalid statement");
// TODO
scc_free(stmt);
return null;
}
scc_vec_push(stmt->compound.block_items, ret);
}
return stmt;
}
static scc_ast_stmt_t *parse_if_statement(scc_parser_t *parser) {
if (!scc_parse_consume_if(parser->lex_stream, SCC_TOK_IF)) {
return null;
}
scc_ast_expr_t *expression = ast_parse_paren_expression(parser);
scc_ast_stmt_t *statement = scc_parse_statement(parser);
scc_ast_stmt_t *stmt = ast_stmt_alloc();
stmt->base.type = SCC_AST_STMT_IF;
stmt->if_stmt.cond = expression;
stmt->if_stmt.then_stmt = statement;
if (scc_parse_consume_if(parser->lex_stream, SCC_TOK_ELSE)) {
stmt->if_stmt.opt_else_stmt = scc_parse_statement(parser);
} else {
stmt->if_stmt.opt_else_stmt = null;
}
return stmt;
}
static scc_ast_stmt_t *parse_switch_statement(scc_parser_t *parser) {
if (!scc_parse_consume_if(parser->lex_stream, SCC_TOK_SWITCH)) {
return null;
}
scc_ast_expr_t *expression = ast_parse_paren_expression(parser);
scc_ast_stmt_t *statement = scc_parse_statement(parser);
scc_ast_stmt_t *stmt = ast_stmt_alloc();
stmt->base.type = SCC_AST_STMT_SWITCH;
stmt->switch_stmt.cond = expression;
stmt->switch_stmt.body = statement;
return stmt;
}
static scc_ast_stmt_t *parse_while_statement(scc_parser_t *parser) {
if (!scc_parse_consume_if(parser->lex_stream, SCC_TOK_WHILE)) {
return null;
}
scc_ast_expr_t *expression = ast_parse_paren_expression(parser);
scc_ast_stmt_t *statement = scc_parse_statement(parser);
scc_ast_stmt_t *stmt = ast_stmt_alloc();
stmt->base.type = SCC_AST_STMT_WHILE;
stmt->while_stmt.cond = expression;
stmt->while_stmt.body = statement;
return stmt;
}
static scc_ast_stmt_t *parse_do_while_statement(scc_parser_t *parser) {
if (!scc_parse_consume_if(parser->lex_stream, SCC_TOK_DO)) {
return null;
}
scc_ast_stmt_t *statement = scc_parse_statement(parser);
if (!scc_parse_consume_if(parser->lex_stream, SCC_TOK_WHILE)) {
LOG_ERROR("Expected 'while' after do.");
// TODO 使用更好的错误处理,未来应当采用更好的内存管理器
scc_free(statement);
return null;
}
scc_ast_expr_t *expression = ast_parse_paren_expression(parser);
scc_ast_stmt_t *stmt = ast_stmt_alloc();
stmt->base.type = SCC_AST_STMT_DO_WHILE;
stmt->do_while_stmt.cond = expression;
stmt->do_while_stmt.body = statement;
return stmt;
}
static scc_ast_stmt_t *parse_for_statement(scc_parser_t *parser) {
if (!scc_parse_consume_if(parser->lex_stream, SCC_TOK_FOR)) {
return null;
}
/*
for ( expression(opt) ; expression(opt) ; expression(opt) ) statement
for ( declaration expression(opt) ; expression(opt) ) statement
*/
if (!scc_parse_consume_if(parser->lex_stream, SCC_TOK_L_PAREN)) {
LOG_ERROR("Expected '(' before like `( expression )` .");
}
scc_ast_stmt_t *stmt = ast_stmt_alloc();
stmt->base.type = SCC_AST_STMT_FOR;
// TODO use decl or expr
stmt->for_stmt.init = (scc_ast_type_t *)scc_parse_expression(parser);
if (!scc_parse_consume_if(parser->lex_stream, SCC_TOK_SEMICOLON)) {
LOG_ERROR("Expected semicolon in for statement.");
}
stmt->for_stmt.cond = scc_parse_expression(parser);
if (!scc_parse_consume_if(parser->lex_stream, SCC_TOK_SEMICOLON)) {
LOG_ERROR("Expected semicolon in for statement.");
}
stmt->for_stmt.iter = scc_parse_expression(parser);
if (!scc_parse_consume_if(parser->lex_stream, SCC_TOK_R_PAREN)) {
LOG_ERROR("Expected ')' after like `( expression )` .");
}
stmt->for_stmt.body = scc_parse_statement(parser);
return stmt;
}
static scc_ast_stmt_t *parse_jump_statement(scc_parser_t *parser) {
scc_ast_stmt_t *stmt = ast_stmt_alloc();
if (scc_parse_consume_if(parser->lex_stream, SCC_TOK_GOTO)) {
stmt->base.type = SCC_AST_STMT_GOTO;
if (scc_parse_is(parser->lex_stream, SCC_TOK_IDENT)) {
const scc_lexer_tok_t *tok =
scc_lexer_stream_current(parser->lex_stream);
stmt->goto_stmt.label = tok->value.cstr.data;
scc_lexer_stream_consume(parser->lex_stream);
} else {
LOG_ERROR("Expected label after goto.");
}
} else if (scc_parse_consume_if(parser->lex_stream, SCC_TOK_CONTINUE)) {
stmt->base.type = SCC_AST_STMT_CONTINUE;
} else if (scc_parse_consume_if(parser->lex_stream, SCC_TOK_BREAK)) {
stmt->base.type = SCC_AST_STMT_BREAK;
} else if (scc_parse_consume_if(parser->lex_stream, SCC_TOK_RETURN)) {
stmt->base.type = SCC_AST_STMT_RETURN;
stmt->return_stmt.expr = scc_parse_expression(parser);
} else {
UNREACHABLE();
}
if (!scc_parse_consume_if(parser->lex_stream, SCC_TOK_SEMICOLON)) {
LOG_ERROR("Expected semicolon after jump statement.");
}
return stmt;
}
static scc_ast_stmt_t *parse_expression_statement(scc_parser_t *parser) {
scc_ast_stmt_t *stmt = ast_stmt_alloc();
stmt->base.type = SCC_AST_STMT_EXPR;
if (scc_parse_consume_if(parser->lex_stream, SCC_TOK_SEMICOLON)) {
stmt->expr.expr = null;
return stmt;
}
stmt->expr.expr = scc_parse_expression(parser);
if (stmt->expr.expr == null) {
// TODO
scc_free(stmt);
return null;
}
if (!scc_parse_consume_if(parser->lex_stream, SCC_TOK_SEMICOLON)) {
LOG_ERROR("Expected semicolon after expression.");
}
return stmt;
}
scc_ast_stmt_t *scc_parse_statement(scc_parser_t *parser) {
const scc_lexer_tok_t *tok = scc_lexer_stream_current(parser->lex_stream);
switch (tok->type) {
/*
(6.8.1)
labeled-statement:
identifier : statement
case constant-expression : statement
default : statement
*/
case SCC_TOK_IDENT:
// 注意需要检测下一个 token 是否为冒号,否则将需要判定成表达式语句
if (!scc_parse_peek_is(parser->lex_stream, 1, SCC_TOK_COLON)) {
break;
}
return parse_label_statement(parser);
case SCC_TOK_CASE:
return parse_case_statement(parser);
case SCC_TOK_DEFAULT:
return parse_default_statement(parser);
/*
(6.8.2)
compound-statement:
{ block-item-list(opt) }
(6.8.2)
block-item-list:
block-item
block-item-list block-item
(6.8.2)
block-item:
declaration
statement
*/
case SCC_TOK_L_BRACE:
return parse_compound_statement(parser);
/*
(6.8.4)
selection-statement:
if ( expression ) statement
if ( expression ) statement else statement
switch ( expression ) statement
*/
case SCC_TOK_IF:
return parse_if_statement(parser);
case SCC_TOK_SWITCH:
return parse_switch_statement(parser);
/*
(6.8.5)
iteration-statement:
while ( expression ) statement
do statement while ( expression );
for ( expression(opt) ; expression(opt) ; expression(opt) )
statement
for ( declaration expression(opt) ; expression(opt) )
statement
*/
case SCC_TOK_WHILE:
return parse_while_statement(parser);
case SCC_TOK_DO:
return parse_do_while_statement(parser);
case SCC_TOK_FOR:
return parse_for_statement(parser);
/*
(6.8.6)
jump-statement:
goto identifier ;
continue ;
break ;
return expression(opt) ;
*/
case SCC_TOK_GOTO:
case SCC_TOK_CONTINUE:
case SCC_TOK_BREAK:
case SCC_TOK_RETURN:
return parse_jump_statement(parser);
default:
break;
}
/*
(6.8.3)
expression-statement:
expression(opt) ;
*/
return parse_expression_statement(parser);
}

1055
libs/parser/src/parse_type.c Normal file

File diff suppressed because it is too large Load Diff

85
libs/parser/src/parser.c Normal file
View File

@@ -0,0 +1,85 @@
/**
* @file parser.c
* @brief 新的解析器实现
*/
#include "parser.h"
#include <log.h>
static void dummy_sema_callback(void *context, scc_ast_node_type_t node_type,
void *node) {
(void)context;
(void)node_type;
(void)node;
return;
}
#define ASSIGN_PTR_OR_DEFAULT(assigned_val, value, default) \
assigned_val = value ? value : default
void scc_parser_init(scc_parser_t *parser, scc_lexer_stream_t *lexer,
scc_sema_callbacks_t *callbacks) {
Assert(parser != null && lexer != null);
parser->lex_stream = lexer;
parser->has_error = false;
parser->translation_unit = null;
if (callbacks) {
ASSIGN_PTR_OR_DEFAULT(parser->sema_callbacks.on_decl,
callbacks->on_decl, dummy_sema_callback);
ASSIGN_PTR_OR_DEFAULT(parser->sema_callbacks.on_stmt,
callbacks->on_stmt, dummy_sema_callback);
ASSIGN_PTR_OR_DEFAULT(parser->sema_callbacks.on_expr,
callbacks->on_expr, dummy_sema_callback);
ASSIGN_PTR_OR_DEFAULT(parser->sema_callbacks.on_type,
callbacks->on_type, dummy_sema_callback);
parser->sema_callbacks.context = callbacks->context;
} else {
parser->sema_callbacks.on_decl = dummy_sema_callback;
parser->sema_callbacks.on_stmt = dummy_sema_callback;
parser->sema_callbacks.on_expr = dummy_sema_callback;
parser->sema_callbacks.on_type = dummy_sema_callback;
parser->sema_callbacks.context = dummy_sema_callback;
}
// // ONLY FOR INIT TYPE
// parser->current_token.type = SCC_TOK_UNKNOWN;
}
void scc_parser_drop(scc_parser_t *parser) {
// TODO: 释放 AST 内存
(void)parser;
}
scc_ast_translation_unit_t *scc_parse_translation_unit(scc_parser_t *parser) {
scc_ast_translation_unit_t *unit =
scc_malloc(sizeof(scc_ast_translation_unit_t));
if (!unit)
return null;
unit->base.type = SCC_AST_TRANSLATION_UNIT;
scc_vec_init(unit->declarations);
/**
* Program := (Declaration | Definition)*
* same as
* Program := Declaration* Definition*
*/
do {
scc_ast_decl_t *decl = scc_parse_declaration(parser);
if (decl != null) {
scc_vec_push(unit->declarations, decl);
} else {
break;
// MAYBE return or next
}
} while (!scc_lexer_tok_match(scc_lexer_stream_current(parser->lex_stream),
SCC_TOK_EOF) &&
!parser->has_error);
if (parser->has_error) {
// TODO: 清理
scc_free(unit);
return null;
}
Assert(unit->base.type == SCC_AST_TRANSLATION_UNIT);
return unit;
}

View File

@@ -0,0 +1,9 @@
[package]
name = "tree_dump"
version = "0.1.0"
authors = []
description = ""
# dependencies = []
# features = {}
# default_features = []

View File

@@ -0,0 +1,104 @@
#ifndef __SCC_TREE_DUMP_H__
#define __SCC_TREE_DUMP_H__
#include <scc_core.h>
#define SCC_TREE_DUMP_VERTICAL "| "
#define SCC_TREE_DUMP_BRANCH "|-"
#define SCC_TREE_DUMP_LAST_BRANCH "`-"
#define SCC_TREE_DUMP_SPACE " "
#define SCC_TREE_DUMP_NODE_COLOR ANSI_FG_BLUE
#define SCC_TREE_DUMP_VALUE_COLOR ANSI_FG_GREEN
#define SCC_TREE_DUMP_BRANCH_COLOR ANSI_FG_YELLOW
#define SCC_TREE_DUMP_RESET_COLOR ANSI_NONE
// #define ANSI_FMT
#define SCC_TREE_DUMP_PRINT_COLORED(ctx, color, before_str, fmt, after_str, \
...) \
scc_printf(before_str "%s" fmt "%s" after_str, \
ctx->use_color ? color : "", ##__VA_ARGS__, \
ctx->use_color ? ANSI_NONE : "");
#define SCC_TREE_DUMP_PRINT_AROUND(ctx, color, around_str, fmt, ...) \
SCC_TREE_DUMP_PRINT_COLORED(ctx, color, around_str, fmt, around_str, \
##__VA_ARGS__)
#define SCC_TREE_DUMP_PRINT_PURE(ctx, color, fmt, ...) \
SCC_TREE_DUMP_PRINT_COLORED(ctx, color, "", fmt, "", ##__VA_ARGS__)
typedef SCC_VEC(cbool) scc_ast_dump_stack_t;
typedef struct {
scc_ast_dump_stack_t stack; ///< 每层是否为最后子节点
cbool use_color; ///< 是否使用颜色输出
const char *vertical;
const char *branch;
const char *last_branch;
const char *space;
const char *node_color; ///< 节点类型颜色
const char *value_color; ///< 值颜色
const char *branch_color; ///< 分支符号颜色
const char *reset_color; ///< 重置颜色
} scc_tree_dump_ctx_t;
static inline void scc_tree_dump_ctx_init(scc_tree_dump_ctx_t *ctx,
cbool use_color) {
ctx->use_color = use_color;
scc_vec_init(ctx->stack);
ctx->vertical = SCC_TREE_DUMP_VERTICAL;
ctx->branch = SCC_TREE_DUMP_BRANCH;
ctx->last_branch = SCC_TREE_DUMP_LAST_BRANCH;
ctx->space = SCC_TREE_DUMP_SPACE;
ctx->node_color = use_color ? SCC_TREE_DUMP_NODE_COLOR : "";
ctx->value_color = use_color ? SCC_TREE_DUMP_VALUE_COLOR : "";
ctx->branch_color = use_color ? SCC_TREE_DUMP_BRANCH_COLOR : "";
ctx->reset_color = use_color ? SCC_TREE_DUMP_RESET_COLOR : "";
}
static inline void scc_tree_dump_ctx_drop(scc_tree_dump_ctx_t *ctx) {
scc_vec_free(ctx->stack);
}
// 打印缩进
static void scc_tree_print_indent(scc_tree_dump_ctx_t *ctx) {
scc_vec_foreach(ctx->stack, i) {
cbool last_child = scc_vec_at(ctx->stack, i);
const char *data = null;
if (i + 1 == scc_vec_size(ctx->stack)) {
// 最后一层打印分支符号
data = last_child ? ctx->last_branch : ctx->branch;
} else {
data = last_child ? ctx->space : ctx->vertical;
}
Assert(data != null);
if (ctx->use_color) {
scc_printf("%s%s%s", ctx->branch_color, data, ctx->reset_color);
} else {
scc_printf("%s", data);
}
}
}
// 推入新的层级到栈中
static inline void scc_tree_dump_push_level(scc_tree_dump_ctx_t *ctx,
cbool is_last_child) {
scc_vec_push(ctx->stack, is_last_child);
}
// 弹出当前层级
static inline void scc_tree_dump_pop_level(scc_tree_dump_ctx_t *ctx) {
(void)scc_vec_pop(ctx->stack);
}
// 获取当前层级深度
static inline usize scc_tree_dump_depth(scc_tree_dump_ctx_t *ctx) {
return scc_vec_size(ctx->stack);
}
#endif /* __SCC_TREE_DUMP_H__ */

View File

@@ -0,0 +1,6 @@
#include <stdio.h>
int main() {
printf("Hello, World!\n");
return 0;
}

View File

@@ -0,0 +1,10 @@
#include <stdio.h>
void test_example() {
printf("Test passed!\n");
}
int main() {
test_example();
return 0;
}

View File

@@ -1,63 +1,60 @@
#include <log.h>
void log_default_handler(log_level_t level, const char *module,
const char *file, int line, const char *message) {
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;
}
static inline int log_snprintf(char *s, size_t n, const char *format, ...) {
int ret;
va_list args;
va_start(args, format);
ret = log_vsnprintf(s, n, format, args);
va_end(args);
return ret;
}
/// @note: 定义 __LOG_NO_COLOR__ 会取消颜色输出
#ifndef __LOG_NO_COLOR__
int log_default_handler(logger_t *module, log_level_t level, const char *file,
int line, const char *func, const char *fmt, ...) {
const char *level_str;
int offset = 0;
va_list args;
va_start(args, fmt);
/* clang-format off */
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;
}
/// @note: 定义 __LOG_NO_COLOR__ 会取消颜色输出
#ifndef __LOG_NO_COLOR__
const char *color_code;
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;
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;
}
log_printf(ANSI_BOLD "%s[%s] - %s - %s:%d | %s" ANSI_NONE "\n", color_code,
level_str, module, file, line, message);
/* clang-format on */
offset =
log_snprintf(module->buf, sizeof(module->buf),
ANSI_BOLD "%s[%s] %s - %s:%d in %s()" ANSI_NONE " ",
color_code, level_str, module->name, file, line, func);
#else
log_printf("[%s] %s:%d | %s: %s\n", level_str, file, line, module, message);
offset = log_snprintf(module->buf, sizeof(module->buf),
"[%s] %s - %s:%d in %s() ", level_str, module->name,
file, line, func);
#endif
/* 然后写入用户消息(如果有) */
if (fmt && fmt[0]) {
log_vsnprintf(module->buf + offset, sizeof(module->buf) - offset, fmt,
args);
}
va_end(args);
log_puts(module->buf);
log_puts("\n");
// for clangd warning
// clang-analyzer-deadcode.DeadStores
(void)color_code;
@@ -65,6 +62,7 @@ void log_default_handler(log_level_t level, const char *module,
if (level & LOG_LEVEL_FATAL) {
log_exit(-LOG_LEVEL_FATAL);
}
return 0;
}
logger_t __default_logger_root = {

View File

@@ -3,17 +3,18 @@
* @brief 日志系统核心模块(支持多级日志、断言和异常处理)
*/
#ifndef __SCC_LOG_H__
#define __SCC_LOG_H__
#ifndef __SCC_LOG_IMPL_H__
#define __SCC_LOG_IMPL_H__
#include "color.h"
#include <stdarg.h>
#ifdef __SCC_LOG_USE_STD_IMPL__
#ifdef __SCC_LOG_IMPL_USE_STD_IMPL__
#include <stdio.h>
#include <stdlib.h>
#define log_snprintf snprintf
#define log_printf printf
#define log_exit exit
#define log_vsnprintf vsnprintf
#define log_puts puts
#define log_exit scc_exit
#endif
#ifdef __GNUC__ // GCC, Clang, ICC
@@ -26,14 +27,14 @@
#define __smcc_log_unreachable()
#endif
#ifndef log_snprintf
#define log_snprintf(...)
#warning "log_snprintf not defined"
#ifndef log_vsnprintf
#define log_vsnprintf(...)
#warning "log_vsnprintf not defined"
#endif
#ifndef log_printf
#define log_printf(...)
#warning "log_printf not defined"
#ifndef log_puts
#define log_puts(...)
#warning "log_puts not defined"
#endif
#ifndef log_exit
@@ -57,36 +58,30 @@ typedef enum log_level {
LOG_LEVEL_ALL = 0xFF, ///< 全级别标志(组合所有日志级别)
} log_level_t;
/**
* @brief 日志处理回调函数类型
* @param level 日志级别
* @param module 模块名称可为NULL
* @param file 源文件名
* @param line 代码行号
* @param message 格式化后的日志消息
* @todo 待实现模块名称,输入的模块名称,都将被忽略
*/
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 512 ///< 单条日志最大缓冲区尺寸
#endif
typedef struct logger logger_t;
typedef int (*log_handler)(logger_t *module, log_level_t level,
const char *file, int line, const char *func,
const char *fmt, ...);
/**
* @brief 日志器实例结构体
*
* 每个日志器实例维护独立的配置和缓冲区
*/
typedef struct logger {
struct logger {
const char *name; ///< 日志器名称(用于模块区分)
log_level_t level; ///< 当前设置的日志级别
log_handler handler; ///< 日志处理回调函数
char buf[LOGGER_MAX_BUF_SIZE]; ///< 格式化缓冲区
} logger_t;
};
void log_default_handler(log_level_t level, const char *module,
const char *file, int line, const char *message);
int log_default_handler(logger_t *module, log_level_t level, const char *file,
int line, const char *func, const char *fmt, ...);
extern logger_t __default_logger_root;
/**
@@ -114,46 +109,38 @@ void log_set_handler(logger_t *logger, log_handler handler);
#define LOG_MAX_MAROC_BUF_SIZE LOGGER_MAX_BUF_SIZE ///< 宏展开缓冲区尺寸
#endif
/**
* @def _LOG
* @brief 内部日志宏(供其他日志宏调用)
* @param _module_ 模块实例NULL表示使用默认日志器
* @param _level_ 日志级别
* @param _msg_ 格式字符串
* @param ... 可变参数列表
*/
#define _LOG(_module_, _level_, _msg_, ...) \
#define SCC_LOG_HANDLE_ARGS(_module_, _level_, ...) \
(_module_), (_level_), __FILE__, __LINE__, __func__, ##__VA_ARGS__
#define SCC_LOG_IMPL(_module_, _level_, _fmt_, ...) \
do { \
logger_t *_logger = _module_; \
if (_logger && _logger->handler && (_logger->level & (_level_))) { \
log_snprintf(_logger->buf, sizeof(_logger->buf), (_msg_), \
##__VA_ARGS__); \
_logger->handler((_level_), _logger->name, __FILE__, __LINE__, \
_logger->buf); \
} \
/* TODO check _module_ is NULL */ \
if ((_module_)->handler && ((_module_)->level & (_level_))) \
(_module_)->handler( \
SCC_LOG_HANDLE_ARGS(_module_, _level_, _fmt_, ##__VA_ARGS__)); \
} while (0)
/* clang-format off */
/// @name 模块日志宏
/// @{
#define MLOG_NOTSET(module, ...)_LOG(module, LOG_LEVEL_NOTSET, __VA_ARGS__) ///< 未分类日志
#define MLOG_DEBUG(module, ...) _LOG(module, LOG_LEVEL_DEBUG, __VA_ARGS__) ///< 调试日志需启用DEBUG级别
#define MLOG_INFO(module, ...) _LOG(module, LOG_LEVEL_INFO, __VA_ARGS__) ///< 信息日志(常规运行日志)
#define MLOG_WARN(module, ...) _LOG(module, LOG_LEVEL_WARN, __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__) ///< 追踪日志(调用栈跟踪)
#define MLOG_NOTSET(module, ...)SCC_LOG_IMPL(module, LOG_LEVEL_NOTSET, __VA_ARGS__) ///< 未分类日志
#define MLOG_DEBUG(module, ...) SCC_LOG_IMPL(module, LOG_LEVEL_DEBUG, __VA_ARGS__) ///< 调试日志需启用DEBUG级别
#define MLOG_INFO(module, ...) SCC_LOG_IMPL(module, LOG_LEVEL_INFO, __VA_ARGS__) ///< 信息日志(常规运行日志)
#define MLOG_WARN(module, ...) SCC_LOG_IMPL(module, LOG_LEVEL_WARN, __VA_ARGS__) ///< 警告日志(潜在问题)
#define MLOG_ERROR(module, ...) SCC_LOG_IMPL(module, LOG_LEVEL_ERROR, __VA_ARGS__) ///< 错误日志(可恢复错误)
#define MLOG_FATAL(module, ...) SCC_LOG_IMPL(module, LOG_LEVEL_FATAL, __VA_ARGS__) ///< 致命错误日志(程序终止前)
#define MLOG_TRACE(module, ...) SCC_LOG_IMPL(module, LOG_LEVEL_TRACE, __VA_ARGS__) ///< 追踪日志(调用栈跟踪)
/// @}
/// @name 快捷日志宏
/// @{
#define LOG_NOTSET(...) _LOG(&__default_logger_root, LOG_LEVEL_NOTSET, __VA_ARGS__) ///< 未分类日志
#define LOG_DEBUG(...) _LOG(&__default_logger_root, LOG_LEVEL_DEBUG, __VA_ARGS__) ///< 调试日志需启用DEBUG级别
#define LOG_INFO(...) _LOG(&__default_logger_root, LOG_LEVEL_INFO, __VA_ARGS__) ///< 信息日志(常规运行日志)
#define LOG_WARN(...) _LOG(&__default_logger_root, LOG_LEVEL_WARN, __VA_ARGS__) ///< 警告日志(潜在问题)
#define LOG_ERROR(...) _LOG(&__default_logger_root, LOG_LEVEL_ERROR, __VA_ARGS__) ///< 错误日志(可恢复错误)
#define LOG_FATAL(...) _LOG(&__default_logger_root, LOG_LEVEL_FATAL, __VA_ARGS__) ///< 致命错误日志(程序终止前)
#define LOG_TRACE(...) _LOG(&__default_logger_root, LOG_LEVEL_TRACE, __VA_ARGS__) ///< 追踪日志(调用栈跟踪)
#define LOG_NOTSET(...) SCC_LOG_IMPL(&__default_logger_root, LOG_LEVEL_NOTSET, __VA_ARGS__) ///< 未分类日志
#define LOG_DEBUG(...) SCC_LOG_IMPL(&__default_logger_root, LOG_LEVEL_DEBUG, __VA_ARGS__) ///< 调试日志需启用DEBUG级别
#define LOG_INFO(...) SCC_LOG_IMPL(&__default_logger_root, LOG_LEVEL_INFO, __VA_ARGS__) ///< 信息日志(常规运行日志)
#define LOG_WARN(...) SCC_LOG_IMPL(&__default_logger_root, LOG_LEVEL_WARN, __VA_ARGS__) ///< 警告日志(潜在问题)
#define LOG_ERROR(...) SCC_LOG_IMPL(&__default_logger_root, LOG_LEVEL_ERROR, __VA_ARGS__) ///< 错误日志(可恢复错误)
#define LOG_FATAL(...) SCC_LOG_IMPL(&__default_logger_root, LOG_LEVEL_FATAL, __VA_ARGS__) ///< 致命错误日志(程序终止前)
#define LOG_TRACE(...) SCC_LOG_IMPL(&__default_logger_root, LOG_LEVEL_TRACE, __VA_ARGS__) ///< 追踪日志(调用栈跟踪)
/// @}
/* clang-format on */
@@ -164,35 +151,48 @@ void log_set_handler(logger_t *logger, log_handler handler);
* @param ... 错误信息参数(格式字符串+参数)
*/
#define _Assert(cond, ...) \
do { \
if (!(cond)) { \
LOG_FATAL(__VA_ARGS__); \
log_exit(1); \
__smcc_log_unreachable(); \
} \
} while (0)
((void)((cond) || \
(__default_logger_root.handler(SCC_LOG_HANDLE_ARGS( \
&__default_logger_root, LOG_LEVEL_FATAL, __VA_ARGS__)), \
log_exit(1), __smcc_log_unreachable(), 0)))
/// @name 断言工具宏
/// @{
#define __INNER_LOG_STR(str) #str
#define __LOG_STR(str) __INNER_LOG_STR(str)
#define __INNERSCC_LOG_IMPL_STR(str) #str
#define _SCC_LOG_IMPL_STR(str) __INNERSCC_LOG_IMPL_STR(str)
#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 `" __LOG_STR(cond) "`") ///< 基础断言检查
AssertFmt(cond, "cond is `" _SCC_LOG_IMPL_STR(cond) "`") ///< 基础断言检查
#define Panic(...) PanicFmt(__VA_ARGS__) ///< 触发致命错误(带自定义消息)
#define TODO() \
PanicFmt("TODO please implement me") ///< 标记未实现代码(触发致命错误)
#define UNREACHABLE() PanicFmt("UNREACHABLE") ///< 触发致命错误(代码不可达)
#define FIXME(str) \
PanicFmt("FIXME " __LOG_STR(str)) ///< 提醒开发者修改代码(触发致命错误)
PanicFmt("FIXME " _SCC_LOG_IMPL_STR( \
str)) ///< 提醒开发者修改代码(触发致命错误)
/// @}
#ifdef __SCC_LOG_IMPORT_SRC__
/**
* @brief 静态断言(编译时)
*
* 利用数组大小不能为负的特性
* 或使用 _Static_assert (C11)
*/
#ifdef static_assert
#undef static_assert
#endif
#if __STDC_VERSION__ >= 201112L
#define static_assert _Static_assert
#else
#define static_assert(cond, msg) extern char __static_assertion[(cond) ? 1 : -1]
#endif
#ifdef __SCC_LOG_IMPL_IMPORT_SRC__
#include "log.c"
#endif
#endif /* __SCC_LOG_H__ */
#endif /* __SCC_LOG_IMPL_H__ */

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,242 @@
/**
* @author (c) Eyal Rozenberg <eyalroz1@gmx.com>
* 2021-2024, Haifa, Palestine/Israel
* @author (c) Marco Paland (info@paland.com)
* 2014-2019, PALANDesign Hannover, Germany
*
* @note Others have made smaller contributions to this file: see the
* contributors page at https://github.com/eyalroz/printf/graphs/contributors
* or ask one of the authors.
*
* @brief Small stand-alone implementation of the printf family of functions
* (`(v)printf`, `(v)s(n)printf` etc., geared towards use on embedded systems
* with a very limited resources.
*
* @note the implementations are thread-safe; re-entrant; use no functions from
* the standard library; and do not dynamically allocate any memory.
*
* @license The MIT License (MIT)
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
* THE SOFTWARE.
*/
#ifndef PRINTF_H_
#define PRINTF_H_
#ifdef PRINTF_INCLUDE_CONFIG_H
#include "printf_config.h"
#endif
#ifdef __cplusplus
# include <cstdarg>
# include <cstddef>
extern "C" {
#else
# include <stdarg.h>
# include <stddef.h>
#endif
#ifdef __GNUC__
# if ((__GNUC__ == 4 && __GNUC_MINOR__>= 4) || __GNUC__ > 4)
# define ATTR_PRINTF(one_based_format_index, first_arg) \
__attribute__((format(gnu_printf, (one_based_format_index), (first_arg))))
# else
# define ATTR_PRINTF(one_based_format_index, first_arg) \
__attribute__((format(printf, (one_based_format_index), (first_arg))))
# endif
# define ATTR_VPRINTF(one_based_format_index) \
ATTR_PRINTF((one_based_format_index), 0)
#else
# define ATTR_PRINTF(one_based_format_index, first_arg)
# define ATTR_VPRINTF(one_based_format_index)
#endif
#ifndef PRINTF_ALIAS_STANDARD_FUNCTION_NAMES_SOFT
#define PRINTF_ALIAS_STANDARD_FUNCTION_NAMES_SOFT 0
#endif
#ifndef PRINTF_ALIAS_STANDARD_FUNCTION_NAMES_HARD
#define PRINTF_ALIAS_STANDARD_FUNCTION_NAMES_HARD 0
#endif
#if PRINTF_ALIAS_STANDARD_FUNCTION_NAMES_HARD
# define printf_ printf
# define sprintf_ sprintf
# define vsprintf_ vsprintf
# define snprintf_ snprintf
# define vsnprintf_ vsnprintf
# define vprintf_ vprintf
#endif
/*
* If you want to include this implementation file directly rather than
* link against it, this will let you control the functions' visibility,
* e.g. make them static so as not to clash with other objects also
* using them.
*/
#ifndef PRINTF_VISIBILITY
#define PRINTF_VISIBILITY
#endif
/**
* Prints/send a single character to some opaque output entity
*
* @note This function is not implemented by the library, only declared; you
* must provide an implementation if you wish to use the @ref printf / @ref
* vprintf function (and possibly for linking against the library, if your
* toolchain does not support discarding unused functions)
*
* @note The output could be as simple as a wrapper for the `write()` system
* call on a Unix-like * system, or even libc's @ref putchar , for replicating
* actual functionality of libc's @ref printf * function; but on an embedded
* system it may involve interaction with a special output device, like a UART,
* etc.
*
* @note in libc's @ref putchar, the parameter type is an int; this was intended
* to support the representation of either a proper character or EOF in a
* variable - but this is really not meaningful to pass into @ref putchar and is
* discouraged today. See further discussion in:
* @link https://stackoverflow.com/q/17452847/1593077
*
* @param c the single character to print
*/
PRINTF_VISIBILITY
void putchar_(char c);
/**
* An implementation of the C standard's printf/vprintf
*
* @note you must implement a @ref putchar_ function for using this function -
* it invokes @ref putchar_ * rather than directly performing any I/O (which
* insulates it from any dependence on the operating system * and external
* libraries).
*
* @param format A string specifying the format of the output, with %-marked
* specifiers of how to interpret additional arguments.
* @param arg Additional arguments to the function, one for each %-specifier in
* @p format
* @return The number of characters written into @p s, not counting the
* terminating null character
*/
/* @{ */
PRINTF_VISIBILITY
int printf_(const char* format, ...) ATTR_PRINTF(1, 2);
PRINTF_VISIBILITY
int vprintf_(const char* format, va_list arg) ATTR_VPRINTF(1);
/* @} */
/**
* An implementation of the C standard's sprintf/vsprintf
*
* @note For security considerations (the potential for exceeding the buffer
* bounds), please consider using the size-constrained variant, @ref snprintf /
* @ref vsnprintf, instead.
*
* @param s An array in which to store the formatted string. It must be large
* enough to fit the formatted output!
* @param format A string specifying the format of the output, with %-marked
* specifiers of how to interpret additional arguments
* @param arg Additional arguments to the function, one for each specifier in
* @p format
* @return The number of characters written into @p s, not counting the
* terminating null character
*/
/* @{ */
PRINTF_VISIBILITY
int sprintf_(char* s, const char* format, ...) ATTR_PRINTF(2, 3);
PRINTF_VISIBILITY
int vsprintf_(char* s, const char* format, va_list arg) ATTR_VPRINTF(2);
/* @} */
/**
* An implementation of the C standard's snprintf/vsnprintf
*
* @param s An array in which to store the formatted string. It must be large
* enough to fit either the entire formatted output, or at least @p n
* characters. Alternatively, it can be NULL, in which case nothing will
* be printed, and only the number of characters which _could_ have been
* printed is tallied and returned.
* @param n The maximum number of characters to write to the array, including
* a terminating null character
* @param format A string specifying the format of the output, with %-marked
* specifiers of how to interpret additional arguments.
* @param arg Additional arguments to the function, one for each specifier in
* @p format
* @return The number of characters that COULD have been written into @p s, not
* counting the terminating null character. A value equal or larger than
* @p n indicates truncation. Only when the returned value is non-negative
* and less than @p n, the null-terminated string has been fully and
* successfully printed.
*/
/* @{ */
PRINTF_VISIBILITY
int snprintf_(char* s, size_t count, const char* format, ...) ATTR_PRINTF(3, 4);
PRINTF_VISIBILITY
int vsnprintf_(char* s, size_t count, const char* format, va_list arg) ATTR_VPRINTF(3);
/* @} */
/**
* printf/vprintf with user-specified output function
*
* An alternative to @ref printf_, in which the output function is specified
* dynamically (rather than @ref putchar_ being used)
*
* @param out An output function which takes one character and a type-erased
* additional parameters
* @param extra_arg The type-erased argument to pass to the output function @p
* out with each call
* @param format A string specifying the format of the output, with %-marked
* specifiers of how to interpret additional arguments.
* @param arg Additional arguments to the function, one for each specifier in
* @p format
* @return The number of characters for which the output f unction was invoked,
* not counting the terminating null character
*
*/
PRINTF_VISIBILITY
int fctprintf(void (*out)(char c, void* extra_arg), void* extra_arg, const char* format, ...) ATTR_PRINTF(3, 4);
PRINTF_VISIBILITY
int vfctprintf(void (*out)(char c, void* extra_arg), void* extra_arg, const char* format, va_list arg) ATTR_VPRINTF(3);
#ifdef __cplusplus
} /* extern "C" */
#endif
#if PRINTF_ALIAS_STANDARD_FUNCTION_NAMES_HARD
# undef printf_
# undef sprintf_
# undef vsprintf_
# undef snprintf_
# undef vsnprintf_
# undef vprintf_
#else
#if PRINTF_ALIAS_STANDARD_FUNCTION_NAMES_SOFT
# define printf printf_
# define sprintf sprintf_
# define vsprintf vsprintf_
# define snprintf snprintf_
# define vsnprintf vsnprintf_
# define vprintf vprintf_
#endif
#endif
#endif /* PRINTF_H_ */

View File

@@ -3,35 +3,31 @@
#include "scc_core_type.h"
/* ====== 内存管理核心接口 ====== */
void *scc_malloc(usize size);
void *scc_calloc(usize count, usize size);
void *scc_realloc(void *ptr, usize new_size);
void scc_free(void *ptr);
/* ====== 文件系统核心接口 ====== */
/* 文件句柄 - 不透明指针 */
typedef struct scc_file *scc_file_t;
/* 文件打开模式 - 只保留编译器真正需要的 */
typedef enum {
SCC_FILE_READ, /* 读取源文件、头文件 */
SCC_FILE_WRITE, /* 写入目标文件、汇编文件 */
SCC_FILE_APPEND /* 日志、调试输出 */
} scc_fmode_t;
/* 核心文件操作 */
scc_file_t scc_fopen(const char *path, scc_fmode_t mode);
void scc_fclose(scc_file_t file);
usize scc_fread(scc_file_t file, void *buffer, usize size);
usize scc_fwrite(scc_file_t file, const void *buffer, usize size);
cbool scc_fexists(const char *path);
/* ====== 输入输出核心接口 ====== */
void scc_snprintf(char *buf, usize size, const char *format, ...);
#include "printf/printf.h"
#define scc_snprintf snprintf_
#define scc_vsnprintf vsnprintf_
#ifdef __SCC_CORE_FMT_IMPL__
#include "printf/printf.c"
#endif
/* 标准输出 - 用于编译进度、结果 */
void scc_printf(const char *format, ...);
@@ -39,8 +35,6 @@ void scc_printf(const char *format, ...);
/* 错误输出 - 用于错误信息、警告 */
void scc_eprintf(const char *format, ...);
/* ====== 系统核心接口 ====== */
/* 程序控制 */
void scc_exit(int code);

View File

@@ -1,12 +1,12 @@
#ifndef __SCC_CORE_LOG_H__
#define __SCC_CORE_LOG_H__
#ifndef log_snprintf
#define log_snprintf scc_snprintf
#ifndef log_vsnprintf
#define log_vsnprintf scc_vsnprintf
#endif
#ifndef log_printf
#define log_printf scc_printf
#ifndef log_puts
#define log_puts(str) scc_printf("%s", str)
#endif
#ifndef log_exit

View File

@@ -30,15 +30,15 @@ struct scc_probe_stream {
/// @brief 移动探针位置并返回字符
int (*next)(scc_probe_stream_t *stream);
/// @brief 回退一个字符(单次后退,探针位置后退一步)
cbool (*back)(scc_probe_stream_t *stream);
/// @brief 移动头指针到探针位置
void (*sync)(scc_probe_stream_t *stream);
/// @brief 重置探针位置到头指针位置
void (*reset)(scc_probe_stream_t *stream);
/// @brief 回退一个字符(单次后退,头指针后退一步)
cbool (*back)(scc_probe_stream_t *stream);
/// @brief 读取指定数量的字符到缓冲区
usize (*read_buf)(scc_probe_stream_t *stream, char *buffer, usize count);

View File

@@ -58,7 +58,8 @@ typedef union scc_cvalue {
char ch;
/* number value */
uint64_t n;
uint64_t u;
int64_t i;
/* string value */
struct {

View File

View File

@@ -2,10 +2,11 @@
#define _CRT_SECURE_NO_WARNINGS
#endif
#define __SCC_CORE_FMT_IMPL__
#include <scc_core_impl.h>
#define __SCC_LOG_IMPORT_SRC__
#define log_snprintf scc_snprintf
#define log_printf scc_printf
#define __SCC_LOG_IMPL_IMPORT_SRC__
#define log_vsnprintf vsnprintf_
#define log_puts(str) scc_printf("%s", str)
#define log_exit scc_exit
#include <log.h>
@@ -15,6 +16,7 @@
#include <stdlib.h>
#include <string.h>
void putchar_(char c) { putchar(c); }
/* ====== 内存管理核心接口实现 ====== */
void *scc_malloc(usize size) { return malloc(size); }
@@ -71,15 +73,6 @@ cbool scc_fexists(const char *path) {
return true;
}
/* ====== 输入输出核心接口实现 ====== */
void scc_snprintf(char *buf, usize size, const char *format, ...) {
va_list args;
va_start(args, format);
vsnprintf(buf, size, format, args); // NOLINT
va_end(args);
}
void scc_printf(const char *format, ...) {
va_list args;
va_start(args, format);

View File

@@ -59,12 +59,13 @@ static cbool mem_probe_stream_back(scc_probe_stream_t *_stream) {
Assert(_stream != null);
scc_mem_probe_stream_t *stream = (scc_mem_probe_stream_t *)_stream;
// 只能回退一个字符,且不能回退到探针位置之前
if (stream->curr_pos == 0 || stream->curr_pos <= stream->probe_pos) {
// 只能回退一个字符
if (stream->probe_pos == 0)
return false;
if (stream->curr_pos + 1 > stream->probe_pos)
return false;
}
stream->curr_pos--;
stream->probe_pos--;
return true;
}

View File

@@ -1,4 +1,4 @@
#include <libcore.h>
#include <scc_core.h>
#include <stdio.h>
int main(void) {

View File

@@ -610,8 +610,6 @@ class GccCompiler(Compiler):
"-DTEST_MODE",
"-O0",
"-g",
"--coverage",
"-fprofile-update=atomic",
"-Wall",
"-Wextra",
],
@@ -650,8 +648,8 @@ class ClangCompiler(Compiler):
"-DTEST_MODE",
"-O0",
"-g",
"--coverage",
"-fprofile-update=atomic",
"-fsanitize=address",
"-fno-omit-frame-pointer",
"-Wall",
"-Wextra",
],
@@ -832,15 +830,23 @@ class PackageBuilder:
"完成 %s 目标,耗时 %s (使用 %d 线程)", self.mode.value, time_str, self.jobs
)
def run(self):
def run(self, args: list[str] | None = None):
"""运行主程序"""
if args is None:
args = []
targets = [
t for t in self.context.get_targets() if t.type == TargetType.MAIN_EXEC
]
if len(targets) != 1:
logger.error("没有可运行的目标")
logger.error(translator.translate("no_targets"))
return
subprocess.run(targets[0].output, check=False)
# 过滤掉 '--' 分隔符
filtered_args = [arg for arg in args if arg != "--"]
logger.info("运行程序: %s %s", targets[0].output, " ".join(filtered_args))
subprocess.run([targets[0].output] + filtered_args, check=False)
def clean(self):
"""清理构建产物"""
@@ -1058,9 +1064,14 @@ def create_parser():
add_common_args(build_parser)
build_parser.set_defaults(mode=BuildMode.DEV)
# run 命令
# run 命令 - 添加剩余参数支持
run_parser = subparsers.add_parser("run", help="运行项目")
add_common_args(run_parser)
run_parser.add_argument(
"args",
nargs=argparse.REMAINDER, # 收集所有剩余参数
help="传递给程序的参数",
)
run_parser.set_defaults(mode=BuildMode.DEV)
# test 命令
@@ -1133,7 +1144,9 @@ def main():
)
elif args.command == "run":
builder.build([TargetType.MAIN_EXEC])
builder.run()
# 传递参数给 run 方法
program_args = getattr(args, "args", [])
builder.run(program_args)
elif args.command == "test":
builder.build([TargetType.TEST_EXEC])
builder.tests(args.filter, args.timeout)