Compare commits
7 Commits
c01e6e1db4
...
2a90e165a5
| Author | SHA1 | Date | |
|---|---|---|---|
| 2a90e165a5 | |||
| c8bf98525d | |||
| 135e874a76 | |||
| 79ee7a657a | |||
| e1cd8c5206 | |||
| 84cff78b86 | |||
| 6c801fbb92 |
4
.gitignore
vendored
4
.gitignore
vendored
@@ -32,3 +32,7 @@ build
|
||||
|
||||
# external
|
||||
external/
|
||||
|
||||
# dot file and svg file
|
||||
*.dot
|
||||
*.svg
|
||||
|
||||
36
README.md
36
README.md
@@ -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)
|
||||
|
||||
## 项目特点
|
||||
|
||||
- **隔离标准库**: 不直接依赖标准库实现,提高可移植性
|
||||
- **轻量化**: 专注于核心功能,减少冗余组件
|
||||
- **模块化**: 采用模块化设计,易于扩展和维护
|
||||
- **自举构建**: 支持通过自身编译器构建项目
|
||||
|
||||
14
justfile
14
justfile
@@ -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
9
libs/ast/cbuild.toml
Normal 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
442
libs/ast/include/ast_def.h
Normal 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__ */
|
||||
20
libs/ast/include/ast_dump.h
Normal file
20
libs/ast/include/ast_dump.h
Normal 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__ */
|
||||
23
libs/ast/include/scc_ast.h
Normal file
23
libs/ast/include/scc_ast.h
Normal 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
716
libs/ast/src/ast_dump.c
Normal 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);
|
||||
}
|
||||
}
|
||||
10
libs/ast/tests/test_main.c
Normal file
10
libs/ast/tests/test_main.c
Normal 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
9
libs/ast2ir/cbuild.toml
Normal file
@@ -0,0 +1,9 @@
|
||||
[package]
|
||||
name = ""
|
||||
version = "0.1.0"
|
||||
authors = []
|
||||
description = ""
|
||||
|
||||
# dependencies = []
|
||||
# features = {}
|
||||
# default_features = []
|
||||
10
libs/ast2ir/include/scc_ast2ir.h
Normal file
10
libs/ast2ir/include/scc_ast2ir.h
Normal 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
553
libs/ast2ir/src/ast2ir.c
Normal 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
10
libs/ast2ir/tests/test_.c
Normal file
@@ -0,0 +1,10 @@
|
||||
#include <stdio.h>
|
||||
|
||||
void test_example() {
|
||||
printf("Test passed!\n");
|
||||
}
|
||||
|
||||
int main() {
|
||||
test_example();
|
||||
return 0;
|
||||
}
|
||||
@@ -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
17
libs/ir/include/ir_base.h
Normal 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__ */
|
||||
174
libs/ir/include/ir_builder.h
Normal file
174
libs/ir/include/ir_builder.h
Normal 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
200
libs/ir/include/ir_ctx.h
Normal 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__ */
|
||||
@@ -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__ */
|
||||
|
||||
@@ -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__ */
|
||||
|
||||
@@ -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__ */
|
||||
|
||||
@@ -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
351
libs/ir/src/ir_builder.c
Normal 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, ¶m_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
345
libs/ir/src/ir_ctx.c
Normal 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;
|
||||
}
|
||||
@@ -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; }
|
||||
@@ -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__ */
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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
10
libs/parser/cbuild.toml
Normal 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" },
|
||||
]
|
||||
113
libs/parser/include/parser.h
Normal file
113
libs/parser/include/parser.h
Normal 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__ */
|
||||
250
libs/parser/src/parse_decl.c
Normal file
250
libs/parser/src/parse_decl.c
Normal 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;
|
||||
}
|
||||
918
libs/parser/src/parse_expr.c
Normal file
918
libs/parser/src/parse_expr.c
Normal 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);
|
||||
}
|
||||
426
libs/parser/src/parse_stmt.c
Normal file
426
libs/parser/src/parse_stmt.c
Normal 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
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
85
libs/parser/src/parser.c
Normal 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;
|
||||
}
|
||||
9
libs/tree_dump/cbuild.toml
Normal file
9
libs/tree_dump/cbuild.toml
Normal file
@@ -0,0 +1,9 @@
|
||||
[package]
|
||||
name = "tree_dump"
|
||||
version = "0.1.0"
|
||||
authors = []
|
||||
description = ""
|
||||
|
||||
# dependencies = []
|
||||
# features = {}
|
||||
# default_features = []
|
||||
104
libs/tree_dump/include/tree_dump.h
Normal file
104
libs/tree_dump/include/tree_dump.h
Normal 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__ */
|
||||
6
libs/tree_dump/src/main.c
Normal file
6
libs/tree_dump/src/main.c
Normal file
@@ -0,0 +1,6 @@
|
||||
#include <stdio.h>
|
||||
|
||||
int main() {
|
||||
printf("Hello, World!\n");
|
||||
return 0;
|
||||
}
|
||||
10
libs/tree_dump/tests/test_.c
Normal file
10
libs/tree_dump/tests/test_.c
Normal file
@@ -0,0 +1,10 @@
|
||||
#include <stdio.h>
|
||||
|
||||
void test_example() {
|
||||
printf("Test passed!\n");
|
||||
}
|
||||
|
||||
int main() {
|
||||
test_example();
|
||||
return 0;
|
||||
}
|
||||
@@ -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 = {
|
||||
|
||||
@@ -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__ */
|
||||
|
||||
1646
runtime/scc_core/include/printf/printf.c
Normal file
1646
runtime/scc_core/include/printf/printf.c
Normal file
File diff suppressed because it is too large
Load Diff
242
runtime/scc_core/include/printf/printf.h
Normal file
242
runtime/scc_core/include/printf/printf.h
Normal 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_ */
|
||||
@@ -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);
|
||||
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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);
|
||||
|
||||
|
||||
@@ -58,7 +58,8 @@ typedef union scc_cvalue {
|
||||
|
||||
char ch;
|
||||
/* number value */
|
||||
uint64_t n;
|
||||
uint64_t u;
|
||||
int64_t i;
|
||||
|
||||
/* string value */
|
||||
struct {
|
||||
|
||||
0
runtime/scc_core/src/cfg.bale_metal.c
Normal file
0
runtime/scc_core/src/cfg.bale_metal.c
Normal 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);
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
#include <libcore.h>
|
||||
#include <scc_core.h>
|
||||
#include <stdio.h>
|
||||
|
||||
int main(void) {
|
||||
|
||||
@@ -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)
|
||||
|
||||
Reference in New Issue
Block a user