feat(ast): 将AST上下文重构为模块并添加字符串池支持
- 将scc_ast_ctx重命名为scc_ast_module以更好地反映其功能 - 添加scc_strpool_t用于统一管理AST节点名称字符串的生命周期 - 实现scc_ast_module_intern函数用于字符串驻留 - 更新所有相关的初始化、销毁和访问函数命名 - 修改内存分配宏以使用新的模块结构 refactor(parser): 更新解析器以使用AST模块和字符串池 - 将解析器中的ast_ctx字段替换为ast_module - 在创建AST节点时使用新的ast_module参数 - 使用scc_ast_module_intern函数处理标识符和字符串字面量 - 确保所有字符串都被正确驻留到模块的字符串池中 refactor(sema): 更新语义分析器使用AST模块 - 将sema_ctx中的ast_ctx字段替换为ast_module - 更新语义分析器初始化函数参数 refactor(ast2ir): 更新AST到IR转换器使用AST模块 - 将ast_ctx字段替换为ast_module - 更新上下文初始化函数参数和实现 fix(cfg): 修复CFG模块中的符号查找错误 - 修正scc_cfg_module_unsafe_get_symbol函数中的边界检查条件 perf(ir): 完善各IR层模块的内存清理机制 - 为HIR模块添加函数和基本块元数据的释放逻辑 - 为MIR和LIR模块完善完整的资源清理和内存释放 - 确保所有分配的元数据结构都能被正确释放 chore(deps): 添加scc_utils依赖到AST库 - 在libs/ast/cbuild.toml中添加对scc_utils的依赖
This commit is contained in:
@@ -7,6 +7,7 @@ description = ""
|
|||||||
dependencies = [
|
dependencies = [
|
||||||
{ name = "tree_dump", path = "../tree_dump" },
|
{ name = "tree_dump", path = "../tree_dump" },
|
||||||
{ name = "scc_pos", path = "../sstream" },
|
{ name = "scc_pos", path = "../sstream" },
|
||||||
|
{ name = "scc_utils", path = "../../runtime/scc_utils" },
|
||||||
]
|
]
|
||||||
# features = {}
|
# features = {}
|
||||||
# default_features = []
|
# default_features = []
|
||||||
|
|||||||
@@ -2,47 +2,59 @@
|
|||||||
#define __SCC_AST_H__
|
#define __SCC_AST_H__
|
||||||
|
|
||||||
#include "scc_ast_def.h"
|
#include "scc_ast_def.h"
|
||||||
|
#include <scc_strpool.h>
|
||||||
|
|
||||||
typedef struct scc_ast_ctx {
|
typedef struct scc_ast_module {
|
||||||
scc_ast_canon_type_vec_t canonical_type_pool;
|
scc_ast_canon_type_vec_t canonical_type_pool;
|
||||||
scc_ast_canon_type_t *builtin_types[SCC_AST_BUILTIN_TYPE_COUNT];
|
scc_ast_canon_type_t *builtin_types[SCC_AST_BUILTIN_TYPE_COUNT];
|
||||||
scc_ast_node_vec_t all_nodes;
|
scc_ast_node_vec_t all_nodes;
|
||||||
} scc_ast_ctx_t;
|
|
||||||
|
|
||||||
void scc_ast_ctx_init(scc_ast_ctx_t *ctx);
|
/** 所有 AST 节点的 name 字符串由 name_pool 统一管理生命周期 */
|
||||||
void scc_ast_ctx_drop(scc_ast_ctx_t *ctx);
|
scc_strpool_t name_pool;
|
||||||
|
} scc_ast_module_t;
|
||||||
|
|
||||||
scc_ast_canon_type_t *scc_ast_ctx_get_builtin_type(scc_ast_ctx_t *ctx,
|
void scc_ast_module_init(scc_ast_module_t *module);
|
||||||
|
void scc_ast_module_drop(scc_ast_module_t *module);
|
||||||
|
|
||||||
|
scc_ast_canon_type_t *
|
||||||
|
scc_ast_module_get_builtin_type(scc_ast_module_t *module,
|
||||||
scc_ast_builtin_type_t kind);
|
scc_ast_builtin_type_t kind);
|
||||||
|
|
||||||
scc_ast_canon_type_t *scc_ast_ctx_alloc_type(scc_ast_ctx_t *ctx);
|
scc_ast_canon_type_t *scc_ast_module_alloc_type(scc_ast_module_t *module);
|
||||||
|
|
||||||
static inline void *scc_ast_ctx_alloc_node(scc_ast_ctx_t *ctx, usize size) {
|
/**
|
||||||
|
* @brief 将字符串 intern 到 module 的 name_pool 中
|
||||||
|
* @return 指向 module 所拥有的持久化副本的指针
|
||||||
|
* (在 module_drop 前始终有效)
|
||||||
|
*/
|
||||||
|
const char *scc_ast_module_intern(scc_ast_module_t *module, const char *str);
|
||||||
|
|
||||||
|
static inline void *scc_ast_module_alloc_node(scc_ast_module_t *module,
|
||||||
|
usize size) {
|
||||||
void *ptr = scc_malloc(size);
|
void *ptr = scc_malloc(size);
|
||||||
if (ptr == nullptr) {
|
if (ptr == nullptr) {
|
||||||
Panic("Out of memory");
|
Panic("Out of memory");
|
||||||
}
|
}
|
||||||
scc_memset(ptr, 0, size);
|
scc_memset(ptr, 0, size);
|
||||||
scc_vec_push(ctx->all_nodes, (scc_ast_node_t *)ptr);
|
scc_vec_push(module->all_nodes, (scc_ast_node_t *)ptr);
|
||||||
return ptr;
|
return ptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
#define SCC_AST_ALLOC(ctx, type) \
|
#define SCC_AST_ALLOC(module, type) \
|
||||||
((type *)scc_ast_ctx_alloc_node(ctx, sizeof(type)))
|
((type *)scc_ast_module_alloc_node(module, sizeof(type)))
|
||||||
#define SCC_AST_ALLOC_QUAL_TYPE(ctx) SCC_AST_ALLOC(ctx, scc_ast_qual_type_t)
|
#define SCC_AST_ALLOC_QUAL_TYPE(module) SCC_AST_ALLOC(module, scc_ast_qual_type_t)
|
||||||
#define SCC_AST_ALLOC_DECL(ctx) SCC_AST_ALLOC(ctx, scc_ast_decl_t)
|
#define SCC_AST_ALLOC_DECL(module) SCC_AST_ALLOC(module, scc_ast_decl_t)
|
||||||
#define SCC_AST_ALLOC_EXPR(ctx) SCC_AST_ALLOC(ctx, scc_ast_expr_t)
|
#define SCC_AST_ALLOC_EXPR(module) SCC_AST_ALLOC(module, scc_ast_expr_t)
|
||||||
#define SCC_AST_ALLOC_STMT(ctx) SCC_AST_ALLOC(ctx, scc_ast_stmt_t)
|
#define SCC_AST_ALLOC_STMT(module) SCC_AST_ALLOC(module, scc_ast_stmt_t)
|
||||||
|
|
||||||
// have defined cannoical_type type
|
|
||||||
static inline void
|
static inline void
|
||||||
scc_ast_type_builtin_init(scc_ast_qual_type_t *type, scc_ast_ctx_t *ctx,
|
scc_ast_type_builtin_init(scc_ast_qual_type_t *type, scc_ast_module_t *module,
|
||||||
scc_ast_builtin_type_t builtin_type, scc_pos_t loc) {
|
scc_ast_builtin_type_t builtin_type, scc_pos_t loc) {
|
||||||
Assert(type != nullptr);
|
Assert(type != nullptr);
|
||||||
type->base.loc = loc;
|
type->base.loc = loc;
|
||||||
type->base.type = SCC_AST_TYPE_BUILTIN;
|
type->base.type = SCC_AST_TYPE_BUILTIN;
|
||||||
type->type = scc_ast_ctx_get_builtin_type(ctx, builtin_type);
|
type->type = scc_ast_module_get_builtin_type(module, builtin_type);
|
||||||
type->quals = (scc_ast_decl_specifier_t){0}; // FIXME
|
type->quals = (scc_ast_decl_specifier_t){0};
|
||||||
}
|
}
|
||||||
|
|
||||||
#endif /* __SCC_AST_H__*/
|
#endif /* __SCC_AST_H__ */
|
||||||
|
|||||||
@@ -1,42 +1,49 @@
|
|||||||
#include <scc_ast.h>
|
#include <scc_ast.h>
|
||||||
|
|
||||||
static scc_ast_canon_type_t *alloc_canonical_type(scc_ast_ctx_t *ctx) {
|
static scc_ast_canon_type_t *alloc_canonical_type(scc_ast_module_t *module) {
|
||||||
scc_ast_canon_type_t *type = scc_malloc(sizeof(scc_ast_canon_type_t));
|
scc_ast_canon_type_t *type = scc_malloc(sizeof(scc_ast_canon_type_t));
|
||||||
if (type == nullptr) {
|
if (type == nullptr) {
|
||||||
Panic("alloc_canonical_type: malloc failed");
|
Panic("alloc_canonical_type: malloc failed");
|
||||||
}
|
}
|
||||||
scc_vec_push(ctx->canonical_type_pool, type);
|
scc_vec_push(module->canonical_type_pool, type);
|
||||||
return type;
|
return type;
|
||||||
}
|
}
|
||||||
|
|
||||||
void scc_ast_ctx_init(scc_ast_ctx_t *ctx) {
|
void scc_ast_module_init(scc_ast_module_t *module) {
|
||||||
scc_vec_init(ctx->canonical_type_pool);
|
scc_vec_init(module->canonical_type_pool);
|
||||||
scc_vec_init(ctx->all_nodes);
|
scc_vec_init(module->all_nodes);
|
||||||
|
scc_strpool_init(&module->name_pool);
|
||||||
|
|
||||||
// 创建全部内置类型
|
|
||||||
for (int i = 0; i < SCC_AST_BUILTIN_TYPE_COUNT; i += 1) {
|
for (int i = 0; i < SCC_AST_BUILTIN_TYPE_COUNT; i += 1) {
|
||||||
scc_ast_canon_type_t *t = alloc_canonical_type(ctx);
|
scc_ast_canon_type_t *t = alloc_canonical_type(module);
|
||||||
t->builtin.type = (scc_ast_builtin_type_t)i; // 直接按顺序对应
|
t->builtin.type = (scc_ast_builtin_type_t)i;
|
||||||
ctx->builtin_types[i] = t;
|
module->builtin_types[i] = t;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void scc_ast_ctx_drop(scc_ast_ctx_t *ctx) {
|
void scc_ast_module_drop(scc_ast_module_t *module) {
|
||||||
// 释放所有规范类型
|
scc_vec_foreach(module->canonical_type_pool, i) {
|
||||||
scc_vec_foreach(ctx->canonical_type_pool, i) {
|
scc_free(module->canonical_type_pool.data[i]);
|
||||||
scc_free(ctx->canonical_type_pool.data[i]);
|
|
||||||
}
|
}
|
||||||
scc_vec_foreach(ctx->all_nodes, i) { scc_free(ctx->all_nodes.data[i]); }
|
scc_vec_foreach(module->all_nodes, i) { scc_free(module->all_nodes.data[i]); }
|
||||||
scc_vec_free(ctx->canonical_type_pool);
|
scc_vec_free(module->canonical_type_pool);
|
||||||
|
scc_strpool_drop(&module->name_pool);
|
||||||
}
|
}
|
||||||
|
|
||||||
scc_ast_canon_type_t *
|
scc_ast_canon_type_t *
|
||||||
scc_ast_ctx_get_builtin_type(scc_ast_ctx_t *ctx, scc_ast_builtin_type_t kind) {
|
scc_ast_module_get_builtin_type(scc_ast_module_t *module,
|
||||||
|
scc_ast_builtin_type_t kind) {
|
||||||
assert(kind < SCC_AST_BUILTIN_TYPE_COUNT &&
|
assert(kind < SCC_AST_BUILTIN_TYPE_COUNT &&
|
||||||
kind > SCC_AST_BUILTIN_TYPE_UNKNOWN);
|
kind > SCC_AST_BUILTIN_TYPE_UNKNOWN);
|
||||||
return ctx->builtin_types[kind];
|
return module->builtin_types[kind];
|
||||||
}
|
}
|
||||||
|
|
||||||
scc_ast_canon_type_t *scc_ast_ctx_alloc_type(scc_ast_ctx_t *ctx) {
|
scc_ast_canon_type_t *scc_ast_module_alloc_type(scc_ast_module_t *module) {
|
||||||
return alloc_canonical_type(ctx);
|
return alloc_canonical_type(module);
|
||||||
|
}
|
||||||
|
|
||||||
|
const char *scc_ast_module_intern(scc_ast_module_t *module, const char *str) {
|
||||||
|
if (str == nullptr)
|
||||||
|
return nullptr;
|
||||||
|
return scc_strpool_intern(&module->name_pool, str);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -16,7 +16,7 @@ typedef struct {
|
|||||||
const scc_abi_type_calc_t *abi;
|
const scc_abi_type_calc_t *abi;
|
||||||
cbool hint_using_value; // 转换时尽可能使用value而不是alloc
|
cbool hint_using_value; // 转换时尽可能使用value而不是alloc
|
||||||
|
|
||||||
scc_ast_ctx_t *ast_ctx;
|
scc_ast_module_t *ast_module;
|
||||||
} scc_ast2ir_ctx_t;
|
} scc_ast2ir_ctx_t;
|
||||||
|
|
||||||
static inline scc_hir_module_t *scc_ast2ir_mir_module(scc_ast2ir_ctx_t *ctx) {
|
static inline scc_hir_module_t *scc_ast2ir_mir_module(scc_ast2ir_ctx_t *ctx) {
|
||||||
@@ -24,7 +24,7 @@ static inline scc_hir_module_t *scc_ast2ir_mir_module(scc_ast2ir_ctx_t *ctx) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
void scc_ast2ir_ctx_init(scc_ast2ir_ctx_t *ctx, const scc_abi_type_calc_t *abi,
|
void scc_ast2ir_ctx_init(scc_ast2ir_ctx_t *ctx, const scc_abi_type_calc_t *abi,
|
||||||
scc_ast_ctx_t *ast_ctx, scc_hir_cprog_t *cprog);
|
scc_ast_module_t *ast_module, scc_hir_cprog_t *cprog);
|
||||||
void scc_ast2ir_ctx_drop(scc_ast2ir_ctx_t *ctx);
|
void scc_ast2ir_ctx_drop(scc_ast2ir_ctx_t *ctx);
|
||||||
|
|
||||||
void scc_ast2ir_run(scc_ast2ir_ctx_t *ctx,
|
void scc_ast2ir_run(scc_ast2ir_ctx_t *ctx,
|
||||||
|
|||||||
@@ -326,8 +326,8 @@ scc_hir_type_ref_t scc_ast2ir_type(scc_ast2ir_ctx_t *ctx,
|
|||||||
return place_ref;
|
return place_ref;
|
||||||
} break;
|
} break;
|
||||||
case SCC_AST_TYPE_ENUM:
|
case SCC_AST_TYPE_ENUM:
|
||||||
scc_ast_canon_type_t *int_canon_type = scc_ast_ctx_get_builtin_type(
|
scc_ast_canon_type_t *int_canon_type = scc_ast_module_get_builtin_type(
|
||||||
ctx->ast_ctx, SCC_AST_BUILTIN_TYPE_INT);
|
ctx->ast_module, SCC_AST_BUILTIN_TYPE_INT);
|
||||||
scc_ast_qual_type_t int_type = {
|
scc_ast_qual_type_t int_type = {
|
||||||
.base.type = SCC_AST_TYPE_BUILTIN,
|
.base.type = SCC_AST_TYPE_BUILTIN,
|
||||||
.type = int_canon_type,
|
.type = int_canon_type,
|
||||||
@@ -1650,8 +1650,9 @@ void scc_ast2ir_decl(scc_ast2ir_ctx_t *ctx, const scc_ast_decl_t *decl,
|
|||||||
.record.name = decl->name,
|
.record.name = decl->name,
|
||||||
};
|
};
|
||||||
scc_ast_qual_type_t type = {
|
scc_ast_qual_type_t type = {
|
||||||
.base.type =
|
.base.type = decl->base.type == SCC_AST_DECL_STRUCT
|
||||||
SCC_AST_DECL_STRUCT ? SCC_AST_TYPE_STRUCT : SCC_AST_TYPE_UNION,
|
? SCC_AST_TYPE_STRUCT
|
||||||
|
: SCC_AST_TYPE_UNION,
|
||||||
.type = &canon_type,
|
.type = &canon_type,
|
||||||
};
|
};
|
||||||
scc_hir_type_ref_t type_ref = scc_ast2ir_type(ctx, &type);
|
scc_hir_type_ref_t type_ref = scc_ast2ir_type(ctx, &type);
|
||||||
@@ -1698,13 +1699,13 @@ void scc_ast2ir_run(scc_ast2ir_ctx_t *ctx,
|
|||||||
}
|
}
|
||||||
|
|
||||||
void scc_ast2ir_ctx_init(scc_ast2ir_ctx_t *ctx, const scc_abi_type_calc_t *abi,
|
void scc_ast2ir_ctx_init(scc_ast2ir_ctx_t *ctx, const scc_abi_type_calc_t *abi,
|
||||||
scc_ast_ctx_t *ast_ctx, scc_hir_cprog_t *cprog) {
|
scc_ast_module_t *ast_module, scc_hir_cprog_t *cprog) {
|
||||||
Assert(ctx != nullptr);
|
Assert(ctx != nullptr);
|
||||||
Assert(abi != nullptr);
|
Assert(abi != nullptr);
|
||||||
Assert(ast_ctx != nullptr);
|
Assert(ast_module != nullptr);
|
||||||
Assert(cprog != nullptr);
|
Assert(cprog != nullptr);
|
||||||
ctx->abi = abi;
|
ctx->abi = abi;
|
||||||
ctx->ast_ctx = ast_ctx;
|
ctx->ast_module = ast_module;
|
||||||
scc_hir_builder_init(&ctx->builder, cprog);
|
scc_hir_builder_init(&ctx->builder, cprog);
|
||||||
scc_hashtable_usize_init(&ctx->ast2ir_cache);
|
scc_hashtable_usize_init(&ctx->ast2ir_cache);
|
||||||
scc_hashtable_usize_init(&ctx->break_cache);
|
scc_hashtable_usize_init(&ctx->break_cache);
|
||||||
|
|||||||
@@ -75,7 +75,7 @@ scc_cfg_module_unsafe_get_symbol(const scc_cfg_module_t *module,
|
|||||||
if (id == SCC_CFG_ID_nullptr) {
|
if (id == SCC_CFG_ID_nullptr) {
|
||||||
Panic("nullptr symbol id");
|
Panic("nullptr symbol id");
|
||||||
}
|
}
|
||||||
if (id >= scc_vec_size(module->bblocks)) {
|
if (id >= scc_vec_size(module->symbols)) {
|
||||||
Panic("invalid symbol id");
|
Panic("invalid symbol id");
|
||||||
}
|
}
|
||||||
return &scc_vec_at(module->symbols, id);
|
return &scc_vec_at(module->symbols, id);
|
||||||
@@ -88,17 +88,29 @@ scc_cfg_symbol_id_t scc_cfg_module_lookup_symbol(const scc_cfg_module_t *module,
|
|||||||
}
|
}
|
||||||
|
|
||||||
void scc_cfg_bblock_add_pred(scc_cfg_bblock_t *bb,
|
void scc_cfg_bblock_add_pred(scc_cfg_bblock_t *bb,
|
||||||
scc_cfg_bblock_id_t pred_id) {}
|
scc_cfg_bblock_id_t pred_id) {
|
||||||
|
(void)bb;
|
||||||
|
(void)pred_id;
|
||||||
|
}
|
||||||
|
|
||||||
void scc_cfg_bblock_remove_pred(scc_cfg_bblock_t *bb,
|
void scc_cfg_bblock_remove_pred(scc_cfg_bblock_t *bb,
|
||||||
scc_cfg_bblock_id_t pred_id) {}
|
scc_cfg_bblock_id_t pred_id) {
|
||||||
|
(void)bb;
|
||||||
|
(void)pred_id;
|
||||||
|
}
|
||||||
|
|
||||||
void scc_cfg_bblock_clear_pred(scc_cfg_bblock_t *bb) {}
|
void scc_cfg_bblock_clear_pred(scc_cfg_bblock_t *bb) { (void)bb; }
|
||||||
|
|
||||||
void scc_cfg_bblock_add_succ(scc_cfg_bblock_t *bb,
|
void scc_cfg_bblock_add_succ(scc_cfg_bblock_t *bb,
|
||||||
scc_cfg_bblock_id_t succ_id) {}
|
scc_cfg_bblock_id_t succ_id) {
|
||||||
|
(void)bb;
|
||||||
|
(void)succ_id;
|
||||||
|
}
|
||||||
|
|
||||||
void scc_cfg_bblock_remove_succ(scc_cfg_bblock_t *bb,
|
void scc_cfg_bblock_remove_succ(scc_cfg_bblock_t *bb,
|
||||||
scc_cfg_bblock_id_t succ_id) {}
|
scc_cfg_bblock_id_t succ_id) {
|
||||||
|
(void)bb;
|
||||||
|
(void)succ_id;
|
||||||
|
}
|
||||||
|
|
||||||
void scc_cfg_bblock_clear_succs(scc_cfg_bblock_t *bb) {}
|
void scc_cfg_bblock_clear_succs(scc_cfg_bblock_t *bb) { (void)bb; }
|
||||||
|
|||||||
@@ -18,6 +18,18 @@ void scc_hir_module_init(scc_hir_module_t *ctx) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
void scc_hir_module_drop(scc_hir_module_t *ctx) {
|
void scc_hir_module_drop(scc_hir_module_t *ctx) {
|
||||||
|
// 释放函数元数据
|
||||||
|
for (usize i = 0; i < ctx->funcs_meta.size; i++) {
|
||||||
|
scc_free(ctx->funcs_meta.data[i]);
|
||||||
|
}
|
||||||
|
scc_vec_free(ctx->funcs_meta);
|
||||||
|
|
||||||
|
// 释放基本块元数据
|
||||||
|
for (usize i = 0; i < ctx->bblock_meta.size; i++) {
|
||||||
|
scc_free(ctx->bblock_meta.data[i]);
|
||||||
|
}
|
||||||
|
scc_vec_free(ctx->bblock_meta);
|
||||||
|
|
||||||
scc_cfg_module_drop(&ctx->cfg_module);
|
scc_cfg_module_drop(&ctx->cfg_module);
|
||||||
|
|
||||||
// 释放所有实体的内部内存
|
// 释放所有实体的内部内存
|
||||||
@@ -36,19 +48,6 @@ void scc_hir_module_drop(scc_hir_module_t *ctx) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// TODO free
|
|
||||||
// ctx->cfg_module.funcs;
|
|
||||||
// for (usize i = 1; i < ctx->bblocks.size; i++) {
|
|
||||||
// scc_hir_bblock_t *bblock = &ctx->bblocks.data[i];
|
|
||||||
// scc_vec_free(bblock->instrs);
|
|
||||||
// }
|
|
||||||
|
|
||||||
// for (usize i = 1; i < ctx->funcs.size; i++) {
|
|
||||||
// scc_hir_func_t *func = &ctx->funcs.data[i];
|
|
||||||
// scc_vec_free(func->params);
|
|
||||||
// scc_vec_free(func->bblocks);
|
|
||||||
// }
|
|
||||||
|
|
||||||
scc_vec_free(ctx->values);
|
scc_vec_free(ctx->values);
|
||||||
scc_vec_free(ctx->types);
|
scc_vec_free(ctx->types);
|
||||||
scc_hashtable_drop(&ctx->uid2value);
|
scc_hashtable_drop(&ctx->uid2value);
|
||||||
|
|||||||
@@ -1,16 +1,28 @@
|
|||||||
#include <scc_lir_module.h>
|
#include <scc_lir_module.h>
|
||||||
|
|
||||||
void scc_lir_module_init(scc_lir_module_t *lir_module) {
|
void scc_lir_module_init(scc_lir_module_t *lir_module) {
|
||||||
// FIXME
|
|
||||||
// lir_module->lir_module
|
|
||||||
scc_vec_init(lir_module->func_metas);
|
scc_vec_init(lir_module->func_metas);
|
||||||
scc_vec_init(lir_module->symbol_metas);
|
scc_vec_init(lir_module->symbol_metas);
|
||||||
}
|
}
|
||||||
|
|
||||||
void scc_lir_module_drop(scc_lir_module_t *lir_module) {
|
void scc_lir_module_drop(scc_lir_module_t *lir_module) {
|
||||||
// FIXME memory leak
|
for (usize i = 0; i < scc_vec_size(lir_module->func_metas); i++) {
|
||||||
|
scc_free(lir_module->func_metas.data[i]);
|
||||||
|
}
|
||||||
|
for (usize i = 0; i < scc_vec_size(lir_module->symbol_metas); i++) {
|
||||||
|
scc_lir_symbol_meta_t *meta = lir_module->symbol_metas.data[i];
|
||||||
|
usize cfg_idx = i + 1; /* cfg_module.symbols[0] is null sentinel */
|
||||||
|
if (cfg_idx < scc_vec_size(lir_module->cfg_module.symbols)) {
|
||||||
|
scc_cfg_symbol_t *sym = &lir_module->cfg_module.symbols.data[cfg_idx];
|
||||||
|
if (sym->kind == SCC_CFG_SYMBOL_KIND_DATA && meta->data.init_data) {
|
||||||
|
scc_free(meta->data.init_data);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
scc_free(meta);
|
||||||
|
}
|
||||||
scc_vec_free(lir_module->func_metas);
|
scc_vec_free(lir_module->func_metas);
|
||||||
scc_vec_free(lir_module->symbol_metas);
|
scc_vec_free(lir_module->symbol_metas);
|
||||||
|
scc_cfg_module_drop(&lir_module->cfg_module);
|
||||||
}
|
}
|
||||||
|
|
||||||
scc_lir_symbol_t *
|
scc_lir_symbol_t *
|
||||||
|
|||||||
@@ -82,7 +82,9 @@ static inline int scc_mir_vreg_lookup(const scc_mir_func_t *func, int vreg,
|
|||||||
static inline scc_mir_stack_slot_t *
|
static inline scc_mir_stack_slot_t *
|
||||||
scc_mir_unsafe_slot(const scc_mir_func_t *func, int slot) {
|
scc_mir_unsafe_slot(const scc_mir_func_t *func, int slot) {
|
||||||
Assert(slot > 0);
|
Assert(slot > 0);
|
||||||
return &scc_vec_at(SCC_MIR_FUNC_META(func)->stack_slots, slot);
|
scc_mir_func_meta_t *meta = SCC_MIR_FUNC_META(func);
|
||||||
|
Assert((usize)slot < scc_vec_size(meta->stack_slots));
|
||||||
|
return &scc_vec_at(meta->stack_slots, slot);
|
||||||
}
|
}
|
||||||
|
|
||||||
#endif /* __SCC_MIR_H__ */
|
#endif /* __SCC_MIR_H__ */
|
||||||
|
|||||||
@@ -8,7 +8,24 @@ void scc_mir_module_init(scc_mir_module_t *mir_module) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
void scc_mir_module_drop(scc_mir_module_t *mir_module) {
|
void scc_mir_module_drop(scc_mir_module_t *mir_module) {
|
||||||
// FIXME memory leak
|
for (usize i = 0; i < scc_vec_size(mir_module->func_metas); i++) {
|
||||||
|
scc_mir_func_meta_t *meta = mir_module->func_metas.data[i];
|
||||||
|
scc_vec_free(meta->stack_slots);
|
||||||
|
scc_hashtable_drop(&meta->vreg2physic);
|
||||||
|
scc_free(meta);
|
||||||
|
}
|
||||||
|
for (usize i = 0; i < scc_vec_size(mir_module->symbol_metas); i++) {
|
||||||
|
scc_mir_symbol_meta_t *meta = mir_module->symbol_metas.data[i];
|
||||||
|
usize cfg_idx = i + 1;
|
||||||
|
if (cfg_idx < scc_vec_size(mir_module->cfg_module.symbols)) {
|
||||||
|
scc_cfg_symbol_t *sym = &mir_module->cfg_module.symbols.data[cfg_idx];
|
||||||
|
if (sym->kind == SCC_CFG_SYMBOL_KIND_DATA && meta->data.init_data) {
|
||||||
|
scc_free(meta->data.init_data);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
scc_free(meta);
|
||||||
|
}
|
||||||
scc_vec_free(mir_module->func_metas);
|
scc_vec_free(mir_module->func_metas);
|
||||||
scc_vec_free(mir_module->symbol_metas);
|
scc_vec_free(mir_module->symbol_metas);
|
||||||
|
scc_cfg_module_drop(&mir_module->cfg_module);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -14,7 +14,7 @@ typedef struct scc_parser {
|
|||||||
scc_lexer_tok_ring_t *ring;
|
scc_lexer_tok_ring_t *ring;
|
||||||
usize checkpoint;
|
usize checkpoint;
|
||||||
|
|
||||||
scc_ast_ctx_t *ast_ctx;
|
scc_ast_module_t *ast_module;
|
||||||
scc_sema_ctx_t *sema_ctx;
|
scc_sema_ctx_t *sema_ctx;
|
||||||
int owned_sema;
|
int owned_sema;
|
||||||
scc_ast_translation_unit_t *translation_unit;
|
scc_ast_translation_unit_t *translation_unit;
|
||||||
@@ -28,7 +28,7 @@ typedef struct scc_parser {
|
|||||||
* @param callbacks 语义分析回调(可为 nullptr)
|
* @param callbacks 语义分析回调(可为 nullptr)
|
||||||
*/
|
*/
|
||||||
void scc_parser_init(scc_parser_t *parser, scc_lexer_tok_ring_t *tok_ring,
|
void scc_parser_init(scc_parser_t *parser, scc_lexer_tok_ring_t *tok_ring,
|
||||||
scc_ast_ctx_t *ast_ctx, scc_sema_ctx_t *callbacks);
|
scc_ast_module_t *ast_module, scc_sema_ctx_t *callbacks);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief 销毁解析器
|
* @brief 销毁解析器
|
||||||
|
|||||||
@@ -29,7 +29,7 @@ struct scc_sema_ctx {
|
|||||||
scc_sema_callback_t on_expr;
|
scc_sema_callback_t on_expr;
|
||||||
scc_sema_callback_t on_type;
|
scc_sema_callback_t on_type;
|
||||||
scc_sema_got_type_t got_type;
|
scc_sema_got_type_t got_type;
|
||||||
scc_ast_ctx_t *ast_ctx;
|
scc_ast_module_t *ast_module;
|
||||||
|
|
||||||
scc_ast_stmt_vec_t break_stack;
|
scc_ast_stmt_vec_t break_stack;
|
||||||
scc_ast_stmt_vec_t continue_stack;
|
scc_ast_stmt_vec_t continue_stack;
|
||||||
@@ -37,7 +37,7 @@ struct scc_sema_ctx {
|
|||||||
void *context;
|
void *context;
|
||||||
};
|
};
|
||||||
|
|
||||||
void scc_sema_init(scc_sema_ctx_t *sema_ctx, scc_ast_ctx_t *ast_ctx);
|
void scc_sema_init(scc_sema_ctx_t *sema_ctx, scc_ast_module_t *ast_module);
|
||||||
void scc_sema_drop(scc_sema_ctx_t *sema_ctx);
|
void scc_sema_drop(scc_sema_ctx_t *sema_ctx);
|
||||||
|
|
||||||
#endif /* __SCC_SEMA_H__ */
|
#endif /* __SCC_SEMA_H__ */
|
||||||
|
|||||||
@@ -2,6 +2,7 @@
|
|||||||
#define __SCC_SEMA_SYMTAB_H__
|
#define __SCC_SEMA_SYMTAB_H__
|
||||||
|
|
||||||
#include <scc_ast.h>
|
#include <scc_ast.h>
|
||||||
|
#include <scc_strpool.h>
|
||||||
#include <scc_utils.h>
|
#include <scc_utils.h>
|
||||||
|
|
||||||
typedef struct scc_parser_scope {
|
typedef struct scc_parser_scope {
|
||||||
@@ -12,6 +13,7 @@ typedef struct scc_parser_scope {
|
|||||||
typedef struct {
|
typedef struct {
|
||||||
scc_sema_scope_t root_scope;
|
scc_sema_scope_t root_scope;
|
||||||
scc_sema_scope_t *current_scope;
|
scc_sema_scope_t *current_scope;
|
||||||
|
scc_strpool_t name_pool; /* 拥有符号名(生成的标签名等)的生命周期 */
|
||||||
} scc_sema_symtab_t;
|
} scc_sema_symtab_t;
|
||||||
|
|
||||||
void scc_sema_symtab_init(scc_sema_symtab_t *symtab);
|
void scc_sema_symtab_init(scc_sema_symtab_t *symtab);
|
||||||
|
|||||||
@@ -187,7 +187,7 @@ scc_ast_expr_t *scc_parse_initializer(scc_parser_t *parser,
|
|||||||
scc_pos_t pos = tok.loc;
|
scc_pos_t pos = tok.loc;
|
||||||
scc_lexer_tok_drop(&tok);
|
scc_lexer_tok_drop(&tok);
|
||||||
|
|
||||||
init = SCC_AST_ALLOC_EXPR(parser->ast_ctx);
|
init = SCC_AST_ALLOC_EXPR(parser->ast_module);
|
||||||
Assert(init != nullptr);
|
Assert(init != nullptr);
|
||||||
scc_ast_expr_vec_t lhs_exprs;
|
scc_ast_expr_vec_t lhs_exprs;
|
||||||
scc_vec_init(lhs_exprs);
|
scc_vec_init(lhs_exprs);
|
||||||
@@ -203,9 +203,9 @@ scc_ast_expr_t *scc_parse_initializer(scc_parser_t *parser,
|
|||||||
tok_ptr = scc_parser_peek(parser);
|
tok_ptr = scc_parser_peek(parser);
|
||||||
if (tok_ptr && tok_ptr->type == SCC_TOK_IDENT) {
|
if (tok_ptr && tok_ptr->type == SCC_TOK_IDENT) {
|
||||||
scc_parser_next_consume(parser, &tok);
|
scc_parser_next_consume(parser, &tok);
|
||||||
lhs = SCC_AST_ALLOC_EXPR(parser->ast_ctx);
|
lhs = SCC_AST_ALLOC_EXPR(parser->ast_module);
|
||||||
Assert(lhs != nullptr);
|
Assert(lhs != nullptr);
|
||||||
scc_ast_expr_member_init(lhs, ptr, scc_str_as_cstr(&tok.lexeme),
|
scc_ast_expr_member_init(lhs, ptr, scc_ast_module_intern(parser->ast_module, scc_str_as_cstr(&tok.lexeme)),
|
||||||
tok.loc);
|
tok.loc);
|
||||||
if (!scc_parser_consume_if(parser, SCC_TOK_ASSIGN)) {
|
if (!scc_parser_consume_if(parser, SCC_TOK_ASSIGN)) {
|
||||||
ptr = lhs;
|
ptr = lhs;
|
||||||
@@ -231,7 +231,7 @@ scc_ast_expr_t *scc_parse_initializer(scc_parser_t *parser,
|
|||||||
if (!scc_parser_consume_if(parser, SCC_TOK_R_BRACKET)) {
|
if (!scc_parser_consume_if(parser, SCC_TOK_R_BRACKET)) {
|
||||||
SCC_ERROR(scc_parser_got_current_pos(parser), "Expected ']'");
|
SCC_ERROR(scc_parser_got_current_pos(parser), "Expected ']'");
|
||||||
}
|
}
|
||||||
lhs = SCC_AST_ALLOC_EXPR(parser->ast_ctx);
|
lhs = SCC_AST_ALLOC_EXPR(parser->ast_module);
|
||||||
Assert(lhs != nullptr);
|
Assert(lhs != nullptr);
|
||||||
scc_ast_expr_array_subscript_init(lhs, ptr, idx, tok_ptr->loc);
|
scc_ast_expr_array_subscript_init(lhs, ptr, idx, tok_ptr->loc);
|
||||||
if (!scc_parser_consume_if(parser, SCC_TOK_ASSIGN)) {
|
if (!scc_parser_consume_if(parser, SCC_TOK_ASSIGN)) {
|
||||||
@@ -285,7 +285,7 @@ CONTINUE:
|
|||||||
if (tok_ptr->type == SCC_TOK_ASSIGN) {
|
if (tok_ptr->type == SCC_TOK_ASSIGN) {
|
||||||
scc_parser_next_consume(parser, nullptr);
|
scc_parser_next_consume(parser, nullptr);
|
||||||
// TODO maybe memory leak
|
// TODO maybe memory leak
|
||||||
scc_ast_expr_t *lvalue = SCC_AST_ALLOC_EXPR(parser->ast_ctx);
|
scc_ast_expr_t *lvalue = SCC_AST_ALLOC_EXPR(parser->ast_module);
|
||||||
scc_ast_expr_lvalue_init(lvalue, decl->var.type, decl->base.loc);
|
scc_ast_expr_lvalue_init(lvalue, decl->var.type, decl->base.loc);
|
||||||
decl->var.init = scc_parse_initializer(parser, lvalue);
|
decl->var.init = scc_parse_initializer(parser, lvalue);
|
||||||
} else if (tok_ptr->type == SCC_TOK_L_BRACE) {
|
} else if (tok_ptr->type == SCC_TOK_L_BRACE) {
|
||||||
@@ -348,7 +348,7 @@ CONTINUE:
|
|||||||
} else if (tok_ptr->type == SCC_TOK_COMMA) {
|
} else if (tok_ptr->type == SCC_TOK_COMMA) {
|
||||||
scc_parser_next_consume(parser, nullptr);
|
scc_parser_next_consume(parser, nullptr);
|
||||||
if (decl_list == nullptr) {
|
if (decl_list == nullptr) {
|
||||||
decl_list = SCC_AST_ALLOC_DECL(parser->ast_ctx);
|
decl_list = SCC_AST_ALLOC_DECL(parser->ast_module);
|
||||||
Assert(decl_list != nullptr);
|
Assert(decl_list != nullptr);
|
||||||
scc_vec_push(decl_list_vec, decl);
|
scc_vec_push(decl_list_vec, decl);
|
||||||
} else {
|
} else {
|
||||||
@@ -365,7 +365,9 @@ CONTINUE:
|
|||||||
}
|
}
|
||||||
|
|
||||||
RETURN:
|
RETURN:
|
||||||
|
scc_vec_free(decl_list_vec);
|
||||||
return decl;
|
return decl;
|
||||||
ERROR:
|
ERROR:
|
||||||
|
scc_vec_free(decl_list_vec);
|
||||||
return nullptr;
|
return nullptr;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -371,7 +371,7 @@ static scc_ast_expr_t *parse_expression_with_precedence(scc_parser_t *parser,
|
|||||||
return nullptr;
|
return nullptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
scc_ast_expr_t *expr = SCC_AST_ALLOC_EXPR(parser->ast_ctx);
|
scc_ast_expr_t *expr = SCC_AST_ALLOC_EXPR(parser->ast_module);
|
||||||
Assert(expr != nullptr);
|
Assert(expr != nullptr);
|
||||||
// FIXME pos
|
// FIXME pos
|
||||||
scc_ast_expr_binary_init(expr, op, left, right, left->base.loc);
|
scc_ast_expr_binary_init(expr, op, left, right, left->base.loc);
|
||||||
@@ -410,7 +410,7 @@ scc_ast_expr_t *scc_parse_assignment_expression(scc_parser_t *parser) {
|
|||||||
return nullptr;
|
return nullptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
scc_ast_expr_t *expr = SCC_AST_ALLOC_EXPR(parser->ast_ctx);
|
scc_ast_expr_t *expr = SCC_AST_ALLOC_EXPR(parser->ast_module);
|
||||||
Assert(expr != nullptr);
|
Assert(expr != nullptr);
|
||||||
scc_ast_expr_binary_init(expr, op, left, right, pos);
|
scc_ast_expr_binary_init(expr, op, left, right, pos);
|
||||||
left = expr;
|
left = expr;
|
||||||
@@ -456,7 +456,7 @@ static scc_ast_expr_t *parse_conditional_expression(scc_parser_t *parser) {
|
|||||||
return nullptr;
|
return nullptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
scc_ast_expr_t *cond = SCC_AST_ALLOC_EXPR(parser->ast_ctx);
|
scc_ast_expr_t *cond = SCC_AST_ALLOC_EXPR(parser->ast_module);
|
||||||
Assert(cond != nullptr);
|
Assert(cond != nullptr);
|
||||||
scc_ast_expr_cond_init(cond, cond_expr, then_expr, else_expr, pos);
|
scc_ast_expr_cond_init(cond, cond_expr, then_expr, else_expr, pos);
|
||||||
cond_expr = cond;
|
cond_expr = cond;
|
||||||
@@ -481,13 +481,13 @@ static scc_ast_expr_t *parse_cast_expression(scc_parser_t *parser) {
|
|||||||
scc_ast_expr_t *operand = parse_cast_expression(parser);
|
scc_ast_expr_t *operand = parse_cast_expression(parser);
|
||||||
if (!operand) {
|
if (!operand) {
|
||||||
// FIXME postfix-expression
|
// FIXME postfix-expression
|
||||||
scc_ast_expr_t *expr = SCC_AST_ALLOC_EXPR(parser->ast_ctx);
|
scc_ast_expr_t *expr = SCC_AST_ALLOC_EXPR(parser->ast_module);
|
||||||
// FIXME pos
|
// FIXME pos
|
||||||
scc_ast_expr_lvalue_init(expr, type, type->base.loc);
|
scc_ast_expr_lvalue_init(expr, type, type->base.loc);
|
||||||
operand = scc_parse_initializer(parser, expr);
|
operand = scc_parse_initializer(parser, expr);
|
||||||
return operand;
|
return operand;
|
||||||
}
|
}
|
||||||
scc_ast_expr_t *expr = SCC_AST_ALLOC_EXPR(parser->ast_ctx);
|
scc_ast_expr_t *expr = SCC_AST_ALLOC_EXPR(parser->ast_module);
|
||||||
Assert(expr != nullptr);
|
Assert(expr != nullptr);
|
||||||
// FIXME pos
|
// FIXME pos
|
||||||
scc_ast_expr_cast_init(expr, type, operand, type->base.loc);
|
scc_ast_expr_cast_init(expr, type, operand, type->base.loc);
|
||||||
@@ -559,7 +559,7 @@ static scc_ast_expr_t *parse_unary_expression(scc_parser_t *parser) {
|
|||||||
return nullptr;
|
return nullptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
scc_ast_expr_t *expr = SCC_AST_ALLOC_EXPR(parser->ast_ctx);
|
scc_ast_expr_t *expr = SCC_AST_ALLOC_EXPR(parser->ast_module);
|
||||||
Assert(expr != nullptr);
|
Assert(expr != nullptr);
|
||||||
scc_ast_expr_unary_init(expr, op, operand, pos);
|
scc_ast_expr_unary_init(expr, op, operand, pos);
|
||||||
return expr;
|
return expr;
|
||||||
@@ -588,7 +588,7 @@ static scc_ast_expr_t *parse_sizeof_expression(scc_parser_t *parser) {
|
|||||||
return nullptr;
|
return nullptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
scc_ast_expr_t *expr = SCC_AST_ALLOC_EXPR(parser->ast_ctx);
|
scc_ast_expr_t *expr = SCC_AST_ALLOC_EXPR(parser->ast_module);
|
||||||
|
|
||||||
if (next->type == SCC_TOK_L_PAREN) {
|
if (next->type == SCC_TOK_L_PAREN) {
|
||||||
scc_parser_store(parser);
|
scc_parser_store(parser);
|
||||||
@@ -643,7 +643,7 @@ static scc_ast_expr_t *parse_postfix_expression(scc_parser_t *parser) {
|
|||||||
if (!scc_parser_consume_if(parser, SCC_TOK_R_PAREN)) {
|
if (!scc_parser_consume_if(parser, SCC_TOK_R_PAREN)) {
|
||||||
SCC_ERROR(scc_parser_got_current_pos(parser), "Expected ')'");
|
SCC_ERROR(scc_parser_got_current_pos(parser), "Expected ')'");
|
||||||
}
|
}
|
||||||
scc_ast_expr_t *expr = SCC_AST_ALLOC_EXPR(parser->ast_ctx);
|
scc_ast_expr_t *expr = SCC_AST_ALLOC_EXPR(parser->ast_module);
|
||||||
scc_ast_expr_lvalue_init(expr, type, pos);
|
scc_ast_expr_lvalue_init(expr, type, pos);
|
||||||
left = scc_parse_initializer(parser, expr);
|
left = scc_parse_initializer(parser, expr);
|
||||||
return left;
|
return left;
|
||||||
@@ -672,7 +672,7 @@ static scc_ast_expr_t *parse_postfix_expression(scc_parser_t *parser) {
|
|||||||
parser_sync(parser);
|
parser_sync(parser);
|
||||||
return nullptr;
|
return nullptr;
|
||||||
}
|
}
|
||||||
scc_ast_expr_t *subscript = SCC_AST_ALLOC_EXPR(parser->ast_ctx);
|
scc_ast_expr_t *subscript = SCC_AST_ALLOC_EXPR(parser->ast_module);
|
||||||
Assert(subscript != nullptr);
|
Assert(subscript != nullptr);
|
||||||
scc_ast_expr_array_subscript_init(subscript, left, index, pos);
|
scc_ast_expr_array_subscript_init(subscript, left, index, pos);
|
||||||
left = subscript;
|
left = subscript;
|
||||||
@@ -709,7 +709,7 @@ static scc_ast_expr_t *parse_postfix_expression(scc_parser_t *parser) {
|
|||||||
return nullptr;
|
return nullptr;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
scc_ast_expr_t *call = SCC_AST_ALLOC_EXPR(parser->ast_ctx);
|
scc_ast_expr_t *call = SCC_AST_ALLOC_EXPR(parser->ast_module);
|
||||||
Assert(call != nullptr);
|
Assert(call != nullptr);
|
||||||
scc_ast_expr_call_init(call, left, &args, pos);
|
scc_ast_expr_call_init(call, left, &args, pos);
|
||||||
left = call;
|
left = call;
|
||||||
@@ -729,9 +729,9 @@ static scc_ast_expr_t *parse_postfix_expression(scc_parser_t *parser) {
|
|||||||
parser_sync(parser);
|
parser_sync(parser);
|
||||||
return nullptr;
|
return nullptr;
|
||||||
}
|
}
|
||||||
const char *name = scc_str_as_cstr(&ident_tok.lexeme);
|
const char *name = scc_ast_module_intern(parser->ast_module, scc_str_as_cstr(&ident_tok.lexeme));
|
||||||
|
|
||||||
scc_ast_expr_t *member = SCC_AST_ALLOC_EXPR(parser->ast_ctx);
|
scc_ast_expr_t *member = SCC_AST_ALLOC_EXPR(parser->ast_module);
|
||||||
Assert(member != nullptr);
|
Assert(member != nullptr);
|
||||||
if (op_tok.type == SCC_TOK_DOT) {
|
if (op_tok.type == SCC_TOK_DOT) {
|
||||||
scc_ast_expr_member_init(member, left, name, ident_tok.loc);
|
scc_ast_expr_member_init(member, left, name, ident_tok.loc);
|
||||||
@@ -750,7 +750,7 @@ static scc_ast_expr_t *parse_postfix_expression(scc_parser_t *parser) {
|
|||||||
if (!scc_parser_next_consume(parser, &op_tok))
|
if (!scc_parser_next_consume(parser, &op_tok))
|
||||||
return left;
|
return left;
|
||||||
scc_ast_expr_op_t op = map_token_to_unary_op(op_tok.type, false);
|
scc_ast_expr_op_t op = map_token_to_unary_op(op_tok.type, false);
|
||||||
scc_ast_expr_t *expr = SCC_AST_ALLOC_EXPR(parser->ast_ctx);
|
scc_ast_expr_t *expr = SCC_AST_ALLOC_EXPR(parser->ast_module);
|
||||||
Assert(expr != nullptr);
|
Assert(expr != nullptr);
|
||||||
scc_ast_expr_unary_init(expr, op, left, op_tok.loc);
|
scc_ast_expr_unary_init(expr, op, left, op_tok.loc);
|
||||||
scc_lexer_tok_drop(&op_tok);
|
scc_lexer_tok_drop(&op_tok);
|
||||||
@@ -785,36 +785,36 @@ static scc_ast_expr_t *parse_primary_expression(scc_parser_t *parser) {
|
|||||||
case SCC_TOK_IDENT: {
|
case SCC_TOK_IDENT: {
|
||||||
if (!scc_parser_next_consume(parser, &tok))
|
if (!scc_parser_next_consume(parser, &tok))
|
||||||
return nullptr;
|
return nullptr;
|
||||||
expr = SCC_AST_ALLOC_EXPR(parser->ast_ctx);
|
expr = SCC_AST_ALLOC_EXPR(parser->ast_module);
|
||||||
Assert(expr != nullptr);
|
Assert(expr != nullptr);
|
||||||
scc_ast_expr_identifier_init(expr, scc_str_as_cstr(&tok.lexeme),
|
scc_ast_expr_identifier_init(expr, scc_ast_module_intern(parser->ast_module, scc_str_as_cstr(&tok.lexeme)),
|
||||||
tok.loc);
|
tok.loc);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case SCC_TOK_INT_LITERAL: {
|
case SCC_TOK_INT_LITERAL: {
|
||||||
if (!scc_parser_next_consume(parser, &tok))
|
if (!scc_parser_next_consume(parser, &tok))
|
||||||
return nullptr;
|
return nullptr;
|
||||||
expr = SCC_AST_ALLOC_EXPR(parser->ast_ctx);
|
expr = SCC_AST_ALLOC_EXPR(parser->ast_module);
|
||||||
Assert(expr != nullptr);
|
Assert(expr != nullptr);
|
||||||
scc_ast_expr_literal_int_init(expr, scc_str_as_cstr(&tok.lexeme), false,
|
scc_ast_expr_literal_int_init(expr, scc_ast_module_intern(parser->ast_module, scc_str_as_cstr(&tok.lexeme)), false,
|
||||||
tok.loc);
|
tok.loc);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case SCC_TOK_FLOAT_LITERAL: {
|
case SCC_TOK_FLOAT_LITERAL: {
|
||||||
if (!scc_parser_next_consume(parser, &tok))
|
if (!scc_parser_next_consume(parser, &tok))
|
||||||
return nullptr;
|
return nullptr;
|
||||||
expr = SCC_AST_ALLOC_EXPR(parser->ast_ctx);
|
expr = SCC_AST_ALLOC_EXPR(parser->ast_module);
|
||||||
Assert(expr != nullptr);
|
Assert(expr != nullptr);
|
||||||
scc_ast_expr_literal_float_init(expr, scc_str_as_cstr(&tok.lexeme),
|
scc_ast_expr_literal_float_init(expr, scc_ast_module_intern(parser->ast_module, scc_str_as_cstr(&tok.lexeme)),
|
||||||
false, tok.loc);
|
false, tok.loc);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case SCC_TOK_CHAR_LITERAL: {
|
case SCC_TOK_CHAR_LITERAL: {
|
||||||
if (!scc_parser_next_consume(parser, &tok))
|
if (!scc_parser_next_consume(parser, &tok))
|
||||||
return nullptr;
|
return nullptr;
|
||||||
expr = SCC_AST_ALLOC_EXPR(parser->ast_ctx);
|
expr = SCC_AST_ALLOC_EXPR(parser->ast_module);
|
||||||
Assert(expr != nullptr);
|
Assert(expr != nullptr);
|
||||||
scc_ast_expr_literal_char_init(expr, scc_str_as_cstr(&tok.lexeme),
|
scc_ast_expr_literal_char_init(expr, scc_ast_module_intern(parser->ast_module, scc_str_as_cstr(&tok.lexeme)),
|
||||||
false, tok.loc);
|
false, tok.loc);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
@@ -835,10 +835,12 @@ static scc_ast_expr_t *parse_primary_expression(scc_parser_t *parser) {
|
|||||||
scc_str_append(&string, &tmp);
|
scc_str_append(&string, &tmp);
|
||||||
}
|
}
|
||||||
|
|
||||||
expr = SCC_AST_ALLOC_EXPR(parser->ast_ctx);
|
const char *pooled_str = scc_ast_module_intern(parser->ast_module, scc_str_as_cstr(&string));
|
||||||
|
scc_str_drop(&string);
|
||||||
|
expr = SCC_AST_ALLOC_EXPR(parser->ast_module);
|
||||||
Assert(expr != nullptr);
|
Assert(expr != nullptr);
|
||||||
// FIXME loc
|
// FIXME loc
|
||||||
scc_ast_expr_literal_string_init(expr, scc_str_as_cstr(&string), true,
|
scc_ast_expr_literal_string_init(expr, pooled_str, false,
|
||||||
tok.loc);
|
tok.loc);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
@@ -880,7 +882,7 @@ scc_ast_expr_t *scc_parse_expression(scc_parser_t *parser) {
|
|||||||
parser_sync(parser);
|
parser_sync(parser);
|
||||||
return nullptr;
|
return nullptr;
|
||||||
}
|
}
|
||||||
scc_ast_expr_t *expr = SCC_AST_ALLOC_EXPR(parser->ast_ctx);
|
scc_ast_expr_t *expr = SCC_AST_ALLOC_EXPR(parser->ast_module);
|
||||||
Assert(expr != nullptr);
|
Assert(expr != nullptr);
|
||||||
scc_ast_expr_binary_init(expr, SCC_AST_OP_COMMA, left, right, pos);
|
scc_ast_expr_binary_init(expr, SCC_AST_OP_COMMA, left, right, pos);
|
||||||
left = expr;
|
left = expr;
|
||||||
|
|||||||
@@ -83,9 +83,9 @@ static scc_ast_stmt_t *parse_label_statement(scc_parser_t *parser,
|
|||||||
Panic("expect stmt");
|
Panic("expect stmt");
|
||||||
}
|
}
|
||||||
|
|
||||||
scc_ast_stmt_t *stmt = SCC_AST_ALLOC_STMT(parser->ast_ctx);
|
scc_ast_stmt_t *stmt = SCC_AST_ALLOC_STMT(parser->ast_module);
|
||||||
Assert(stmt != nullptr);
|
Assert(stmt != nullptr);
|
||||||
scc_ast_stmt_label_init(stmt, scc_str_as_cstr(&tok.lexeme), statement, pos);
|
scc_ast_stmt_label_init(stmt, scc_ast_module_intern(parser->ast_module, scc_str_as_cstr(&tok.lexeme)), statement, pos);
|
||||||
return stmt;
|
return stmt;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -114,7 +114,7 @@ static scc_ast_stmt_t *parse_case_statement(scc_parser_t *parser,
|
|||||||
Panic("expect stmt");
|
Panic("expect stmt");
|
||||||
}
|
}
|
||||||
|
|
||||||
scc_ast_stmt_t *stmt = SCC_AST_ALLOC_STMT(parser->ast_ctx);
|
scc_ast_stmt_t *stmt = SCC_AST_ALLOC_STMT(parser->ast_module);
|
||||||
scc_ast_stmt_case_init(stmt, expr, statement, pos);
|
scc_ast_stmt_case_init(stmt, expr, statement, pos);
|
||||||
return stmt;
|
return stmt;
|
||||||
}
|
}
|
||||||
@@ -136,7 +136,7 @@ static scc_ast_stmt_t *parse_default_statement(scc_parser_t *parser,
|
|||||||
Panic("expect stmt");
|
Panic("expect stmt");
|
||||||
}
|
}
|
||||||
|
|
||||||
scc_ast_stmt_t *stmt = SCC_AST_ALLOC_STMT(parser->ast_ctx);
|
scc_ast_stmt_t *stmt = SCC_AST_ALLOC_STMT(parser->ast_module);
|
||||||
scc_ast_stmt_default_init(stmt, statement, pos);
|
scc_ast_stmt_default_init(stmt, statement, pos);
|
||||||
return stmt;
|
return stmt;
|
||||||
}
|
}
|
||||||
@@ -168,7 +168,7 @@ static scc_ast_stmt_t *parse_compound_statement(scc_parser_t *parser,
|
|||||||
}
|
}
|
||||||
scc_sema_stmt(parser, scc_ast_stmt_t_END, nullptr);
|
scc_sema_stmt(parser, scc_ast_stmt_t_END, nullptr);
|
||||||
|
|
||||||
scc_ast_stmt_t *stmt = SCC_AST_ALLOC_STMT(parser->ast_ctx);
|
scc_ast_stmt_t *stmt = SCC_AST_ALLOC_STMT(parser->ast_module);
|
||||||
scc_ast_stmt_compound_init(stmt, &block_items, pos);
|
scc_ast_stmt_compound_init(stmt, &block_items, pos);
|
||||||
return stmt;
|
return stmt;
|
||||||
}
|
}
|
||||||
@@ -188,7 +188,7 @@ static scc_ast_stmt_t *parse_if_statement(scc_parser_t *parser, scc_pos_t pos) {
|
|||||||
opt_else = nullptr;
|
opt_else = nullptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
scc_ast_stmt_t *stmt = SCC_AST_ALLOC_STMT(parser->ast_ctx);
|
scc_ast_stmt_t *stmt = SCC_AST_ALLOC_STMT(parser->ast_module);
|
||||||
scc_ast_stmt_if_init(stmt, expression, statement, opt_else, pos);
|
scc_ast_stmt_if_init(stmt, expression, statement, opt_else, pos);
|
||||||
return stmt;
|
return stmt;
|
||||||
}
|
}
|
||||||
@@ -198,7 +198,7 @@ static scc_ast_stmt_t *parse_switch_statement(scc_parser_t *parser,
|
|||||||
if (!scc_parser_consume_if(parser, SCC_TOK_SWITCH)) {
|
if (!scc_parser_consume_if(parser, SCC_TOK_SWITCH)) {
|
||||||
return nullptr;
|
return nullptr;
|
||||||
}
|
}
|
||||||
scc_ast_stmt_t *stmt = SCC_AST_ALLOC_STMT(parser->ast_ctx);
|
scc_ast_stmt_t *stmt = SCC_AST_ALLOC_STMT(parser->ast_module);
|
||||||
stmt->base.type = SCC_AST_STMT_SWITCH;
|
stmt->base.type = SCC_AST_STMT_SWITCH;
|
||||||
|
|
||||||
scc_ast_expr_t *expression = ast_parse_paren_expression(parser);
|
scc_ast_expr_t *expression = ast_parse_paren_expression(parser);
|
||||||
@@ -216,7 +216,7 @@ static scc_ast_stmt_t *parse_while_statement(scc_parser_t *parser,
|
|||||||
if (!scc_parser_consume_if(parser, SCC_TOK_WHILE)) {
|
if (!scc_parser_consume_if(parser, SCC_TOK_WHILE)) {
|
||||||
return nullptr;
|
return nullptr;
|
||||||
}
|
}
|
||||||
scc_ast_stmt_t *stmt = SCC_AST_ALLOC_STMT(parser->ast_ctx);
|
scc_ast_stmt_t *stmt = SCC_AST_ALLOC_STMT(parser->ast_module);
|
||||||
stmt->base.type = SCC_AST_STMT_WHILE;
|
stmt->base.type = SCC_AST_STMT_WHILE;
|
||||||
|
|
||||||
scc_ast_expr_t *expression = ast_parse_paren_expression(parser);
|
scc_ast_expr_t *expression = ast_parse_paren_expression(parser);
|
||||||
@@ -234,7 +234,7 @@ static scc_ast_stmt_t *parse_do_while_statement(scc_parser_t *parser,
|
|||||||
if (!scc_parser_consume_if(parser, SCC_TOK_DO)) {
|
if (!scc_parser_consume_if(parser, SCC_TOK_DO)) {
|
||||||
return nullptr;
|
return nullptr;
|
||||||
}
|
}
|
||||||
scc_ast_stmt_t *stmt = SCC_AST_ALLOC_STMT(parser->ast_ctx);
|
scc_ast_stmt_t *stmt = SCC_AST_ALLOC_STMT(parser->ast_module);
|
||||||
stmt->base.type = SCC_AST_STMT_DO_WHILE;
|
stmt->base.type = SCC_AST_STMT_DO_WHILE;
|
||||||
|
|
||||||
scc_sema_stmt(parser, scc_ast_stmt_t_BEGIN, stmt);
|
scc_sema_stmt(parser, scc_ast_stmt_t_BEGIN, stmt);
|
||||||
@@ -272,7 +272,7 @@ static scc_ast_stmt_t *parse_for_statement(scc_parser_t *parser,
|
|||||||
SCC_ERROR(scc_parser_got_current_pos(parser),
|
SCC_ERROR(scc_parser_got_current_pos(parser),
|
||||||
"Expected '(' before like `( expression )` .");
|
"Expected '(' before like `( expression )` .");
|
||||||
}
|
}
|
||||||
scc_ast_stmt_t *stmt = SCC_AST_ALLOC_STMT(parser->ast_ctx);
|
scc_ast_stmt_t *stmt = SCC_AST_ALLOC_STMT(parser->ast_module);
|
||||||
stmt->base.type = SCC_AST_STMT_FOR;
|
stmt->base.type = SCC_AST_STMT_FOR;
|
||||||
|
|
||||||
scc_ast_node_t *init = nullptr;
|
scc_ast_node_t *init = nullptr;
|
||||||
@@ -314,12 +314,12 @@ static scc_ast_stmt_t *parse_for_statement(scc_parser_t *parser,
|
|||||||
|
|
||||||
static scc_ast_stmt_t *parse_jump_statement(scc_parser_t *parser,
|
static scc_ast_stmt_t *parse_jump_statement(scc_parser_t *parser,
|
||||||
scc_pos_t pos) {
|
scc_pos_t pos) {
|
||||||
scc_ast_stmt_t *stmt = SCC_AST_ALLOC_STMT(parser->ast_ctx);
|
scc_ast_stmt_t *stmt = SCC_AST_ALLOC_STMT(parser->ast_module);
|
||||||
|
|
||||||
if (scc_parser_consume_if(parser, SCC_TOK_GOTO)) {
|
if (scc_parser_consume_if(parser, SCC_TOK_GOTO)) {
|
||||||
scc_lexer_tok_t tok = {0};
|
scc_lexer_tok_t tok = {0};
|
||||||
if (scc_parser_next_consume(parser, &tok)) {
|
if (scc_parser_next_consume(parser, &tok)) {
|
||||||
scc_ast_stmt_goto_init(stmt, scc_str_as_cstr(&tok.lexeme), pos);
|
scc_ast_stmt_goto_init(stmt, scc_ast_module_intern(parser->ast_module, scc_str_as_cstr(&tok.lexeme)), pos);
|
||||||
} else {
|
} else {
|
||||||
SCC_ERROR(scc_parser_got_current_pos(parser),
|
SCC_ERROR(scc_parser_got_current_pos(parser),
|
||||||
"Expected label after goto.");
|
"Expected label after goto.");
|
||||||
@@ -345,7 +345,7 @@ static scc_ast_stmt_t *parse_expression_statement(scc_parser_t *parser,
|
|||||||
scc_pos_t pos) {
|
scc_pos_t pos) {
|
||||||
|
|
||||||
if (scc_parser_consume_if(parser, SCC_TOK_SEMICOLON)) {
|
if (scc_parser_consume_if(parser, SCC_TOK_SEMICOLON)) {
|
||||||
scc_ast_stmt_t *stmt = SCC_AST_ALLOC_STMT(parser->ast_ctx);
|
scc_ast_stmt_t *stmt = SCC_AST_ALLOC_STMT(parser->ast_module);
|
||||||
scc_ast_stmt_expr_init(stmt, nullptr, pos);
|
scc_ast_stmt_expr_init(stmt, nullptr, pos);
|
||||||
return stmt;
|
return stmt;
|
||||||
}
|
}
|
||||||
@@ -355,7 +355,7 @@ static scc_ast_stmt_t *parse_expression_statement(scc_parser_t *parser,
|
|||||||
return nullptr;
|
return nullptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
scc_ast_stmt_t *stmt = SCC_AST_ALLOC_STMT(parser->ast_ctx);
|
scc_ast_stmt_t *stmt = SCC_AST_ALLOC_STMT(parser->ast_module);
|
||||||
scc_ast_stmt_expr_init(stmt, expr, pos);
|
scc_ast_stmt_expr_init(stmt, expr, pos);
|
||||||
|
|
||||||
if (!scc_parser_consume_if(parser, SCC_TOK_SEMICOLON)) {
|
if (!scc_parser_consume_if(parser, SCC_TOK_SEMICOLON)) {
|
||||||
|
|||||||
@@ -526,9 +526,9 @@ static scc_ast_qual_type_t *build_type_from_info(scc_parser_t *parser,
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
scc_ast_ctx_get_builtin_type(parser->ast_ctx, builtin);
|
scc_ast_module_get_builtin_type(parser->ast_module, builtin);
|
||||||
scc_ast_qual_type_t *type = SCC_AST_ALLOC_QUAL_TYPE(parser->ast_ctx);
|
scc_ast_qual_type_t *type = SCC_AST_ALLOC_QUAL_TYPE(parser->ast_module);
|
||||||
scc_ast_type_builtin_init(type, parser->ast_ctx, builtin, pos);
|
scc_ast_type_builtin_init(type, parser->ast_module, builtin, pos);
|
||||||
return type;
|
return type;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -551,7 +551,7 @@ static scc_ast_qual_type_t *parse_record_type(scc_parser_t *parser,
|
|||||||
if (tok_ptr->type == SCC_TOK_IDENT) {
|
if (tok_ptr->type == SCC_TOK_IDENT) {
|
||||||
scc_parser_next_consume(parser, &tok);
|
scc_parser_next_consume(parser, &tok);
|
||||||
tok_ptr = scc_parser_peek(parser);
|
tok_ptr = scc_parser_peek(parser);
|
||||||
name = scc_str_as_cstr(&tok.lexeme);
|
name = scc_ast_module_intern(parser->ast_module, scc_str_as_cstr(&tok.lexeme));
|
||||||
} else if (tok_ptr->type != SCC_TOK_L_BRACE) {
|
} else if (tok_ptr->type != SCC_TOK_L_BRACE) {
|
||||||
SCC_ERROR(scc_parser_got_current_pos(parser),
|
SCC_ERROR(scc_parser_got_current_pos(parser),
|
||||||
"Expected name in struct/union/enum specifier");
|
"Expected name in struct/union/enum specifier");
|
||||||
@@ -581,8 +581,8 @@ static scc_ast_qual_type_t *parse_record_type(scc_parser_t *parser,
|
|||||||
|
|
||||||
type = scc_parse_got_type(parser, scc_str_as_cstr(&symbol_name));
|
type = scc_parse_got_type(parser, scc_str_as_cstr(&symbol_name));
|
||||||
if (type == nullptr) {
|
if (type == nullptr) {
|
||||||
scc_ast_canon_type_t *canon = scc_ast_ctx_alloc_type(parser->ast_ctx);
|
scc_ast_canon_type_t *canon = scc_ast_module_alloc_type(parser->ast_module);
|
||||||
scc_ast_decl_t *decl = SCC_AST_ALLOC_DECL(parser->ast_ctx);
|
scc_ast_decl_t *decl = SCC_AST_ALLOC_DECL(parser->ast_module);
|
||||||
|
|
||||||
scc_ast_node_kind_t decl_kind;
|
scc_ast_node_kind_t decl_kind;
|
||||||
switch (type_kind) {
|
switch (type_kind) {
|
||||||
@@ -607,7 +607,7 @@ static scc_ast_qual_type_t *parse_record_type(scc_parser_t *parser,
|
|||||||
}
|
}
|
||||||
|
|
||||||
scc_ast_qual_type_t *qual_type =
|
scc_ast_qual_type_t *qual_type =
|
||||||
SCC_AST_ALLOC_QUAL_TYPE(parser->ast_ctx);
|
SCC_AST_ALLOC_QUAL_TYPE(parser->ast_module);
|
||||||
_scc_ast_type_record_init(qual_type, canon, type_kind, name, decl,
|
_scc_ast_type_record_init(qual_type, canon, type_kind, name, decl,
|
||||||
*pos);
|
*pos);
|
||||||
scc_parse_type_sema(parser, qual_type);
|
scc_parse_type_sema(parser, qual_type);
|
||||||
@@ -747,10 +747,10 @@ static scc_ast_qual_type_t *parse_enum_type(scc_parser_t *parser) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
scc_ast_decl_t *enum_item_decl =
|
scc_ast_decl_t *enum_item_decl =
|
||||||
SCC_AST_ALLOC_DECL(parser->ast_ctx);
|
SCC_AST_ALLOC_DECL(parser->ast_module);
|
||||||
Assert(enum_item_decl != nullptr);
|
Assert(enum_item_decl != nullptr);
|
||||||
scc_ast_decl_val_init(enum_item_decl, type,
|
scc_ast_decl_val_init(enum_item_decl, type,
|
||||||
scc_str_as_cstr(&tok.lexeme), enum_item_init,
|
scc_ast_module_intern(parser->ast_module, scc_str_as_cstr(&tok.lexeme)), enum_item_init,
|
||||||
tok.loc);
|
tok.loc);
|
||||||
scc_vec_push(decl->record.fields, enum_item_decl);
|
scc_vec_push(decl->record.fields, enum_item_decl);
|
||||||
|
|
||||||
@@ -939,14 +939,14 @@ parse_pointer(scc_parser_t *parser, scc_ast_qual_type_t *pointee,
|
|||||||
scc_pos_t pos = tok_ptr->loc;
|
scc_pos_t pos = tok_ptr->loc;
|
||||||
scc_parser_next_consume(parser, nullptr);
|
scc_parser_next_consume(parser, nullptr);
|
||||||
|
|
||||||
scc_ast_qual_type_t *pointer = SCC_AST_ALLOC_QUAL_TYPE(parser->ast_ctx);
|
scc_ast_qual_type_t *pointer = SCC_AST_ALLOC_QUAL_TYPE(parser->ast_module);
|
||||||
if (pointee == nullptr) {
|
if (pointee == nullptr) {
|
||||||
Assert(delay_pointee_ptr != nullptr);
|
Assert(delay_pointee_ptr != nullptr);
|
||||||
*delay_pointee_ptr = pointer;
|
*delay_pointee_ptr = pointer;
|
||||||
pointee = pointer;
|
pointee = pointer;
|
||||||
}
|
}
|
||||||
|
|
||||||
scc_ast_canon_type_t *canon = scc_ast_ctx_alloc_type(parser->ast_ctx);
|
scc_ast_canon_type_t *canon = scc_ast_module_alloc_type(parser->ast_module);
|
||||||
scc_ast_type_pointer_init(pointer, canon, pointee, pos);
|
scc_ast_type_pointer_init(pointer, canon, pointee, pos);
|
||||||
pointer->quals = parse_type_qualifier_list(parser, pointer->quals);
|
pointer->quals = parse_type_qualifier_list(parser, pointer->quals);
|
||||||
|
|
||||||
@@ -981,7 +981,7 @@ static void parse_parameter_type_list(scc_parser_t *parser,
|
|||||||
}
|
}
|
||||||
|
|
||||||
// TODO Check validation
|
// TODO Check validation
|
||||||
param = SCC_AST_ALLOC_DECL(parser->ast_ctx);
|
param = SCC_AST_ALLOC_DECL(parser->ast_module);
|
||||||
Assert(param != nullptr);
|
Assert(param != nullptr);
|
||||||
scc_ast_decl_param_init(param, decl->var.type, decl->name,
|
scc_ast_decl_param_init(param, decl->var.type, decl->name,
|
||||||
scc_vec_size(*params), decl->base.loc);
|
scc_vec_size(*params), decl->base.loc);
|
||||||
@@ -998,11 +998,11 @@ static void parse_parameter_type_list(scc_parser_t *parser,
|
|||||||
scc_parser_next_consume(parser, nullptr);
|
scc_parser_next_consume(parser, nullptr);
|
||||||
tok_ptr = scc_parser_peek(parser);
|
tok_ptr = scc_parser_peek(parser);
|
||||||
if (tok_ptr->type == SCC_TOK_ELLIPSIS) {
|
if (tok_ptr->type == SCC_TOK_ELLIPSIS) {
|
||||||
param = SCC_AST_ALLOC_DECL(parser->ast_ctx);
|
param = SCC_AST_ALLOC_DECL(parser->ast_module);
|
||||||
Assert(param != nullptr);
|
Assert(param != nullptr);
|
||||||
// FIXME
|
// FIXME
|
||||||
type = SCC_AST_ALLOC_QUAL_TYPE(parser->ast_ctx);
|
type = SCC_AST_ALLOC_QUAL_TYPE(parser->ast_module);
|
||||||
scc_ast_type_builtin_init(type, parser->ast_ctx,
|
scc_ast_type_builtin_init(type, parser->ast_module,
|
||||||
SCC_AST_BUILTIN_TYPE_VA_LIST,
|
SCC_AST_BUILTIN_TYPE_VA_LIST,
|
||||||
tok_ptr->loc);
|
tok_ptr->loc);
|
||||||
scc_ast_decl_param_init(param, type, nullptr, scc_vec_size(*params),
|
scc_ast_decl_param_init(param, type, nullptr, scc_vec_size(*params),
|
||||||
@@ -1112,7 +1112,7 @@ parse_direct_declarator(scc_parser_t *parser, scc_ast_qual_type_t *base,
|
|||||||
scc_lexer_tok_t *tok_ident) {
|
scc_lexer_tok_t *tok_ident) {
|
||||||
const scc_lexer_tok_t *tok_ptr = nullptr;
|
const scc_lexer_tok_t *tok_ptr = nullptr;
|
||||||
scc_ast_qual_type_t *ret = nullptr;
|
scc_ast_qual_type_t *ret = nullptr;
|
||||||
scc_ast_canon_type_t *canon = scc_ast_ctx_alloc_type(parser->ast_ctx);
|
scc_ast_canon_type_t *canon = scc_ast_module_alloc_type(parser->ast_module);
|
||||||
// direct-abstract-declarator
|
// direct-abstract-declarator
|
||||||
tok_ptr = scc_parser_peek(parser);
|
tok_ptr = scc_parser_peek(parser);
|
||||||
if (tok_ptr == nullptr) {
|
if (tok_ptr == nullptr) {
|
||||||
@@ -1137,7 +1137,7 @@ parse_direct_declarator(scc_parser_t *parser, scc_ast_qual_type_t *base,
|
|||||||
if (parse_function_parameters_start(parser)) {
|
if (parse_function_parameters_start(parser)) {
|
||||||
scc_ast_decl_vec_t params;
|
scc_ast_decl_vec_t params;
|
||||||
parse_function_parameters(parser, ¶ms);
|
parse_function_parameters(parser, ¶ms);
|
||||||
ret = SCC_AST_ALLOC_QUAL_TYPE(parser->ast_ctx);
|
ret = SCC_AST_ALLOC_QUAL_TYPE(parser->ast_module);
|
||||||
// FIXME
|
// FIXME
|
||||||
scc_ast_type_function_init(ret, canon, base, ¶ms,
|
scc_ast_type_function_init(ret, canon, base, ¶ms,
|
||||||
base->base.loc);
|
base->base.loc);
|
||||||
@@ -1162,7 +1162,7 @@ parse_direct_declarator(scc_parser_t *parser, scc_ast_qual_type_t *base,
|
|||||||
} else if (tok_ptr->type == SCC_TOK_L_BRACKET) {
|
} else if (tok_ptr->type == SCC_TOK_L_BRACKET) {
|
||||||
// [] SCC_TOK_L_BRACKET
|
// [] SCC_TOK_L_BRACKET
|
||||||
scc_ast_expr_t *size = parse_array_size_type(parser);
|
scc_ast_expr_t *size = parse_array_size_type(parser);
|
||||||
scc_ast_qual_type_t *ret = SCC_AST_ALLOC_QUAL_TYPE(parser->ast_ctx);
|
scc_ast_qual_type_t *ret = SCC_AST_ALLOC_QUAL_TYPE(parser->ast_module);
|
||||||
base =
|
base =
|
||||||
parse_direct_declarator(parser, base, delay_pointee_ptr, tok_ident);
|
parse_direct_declarator(parser, base, delay_pointee_ptr, tok_ident);
|
||||||
// FIXME
|
// FIXME
|
||||||
@@ -1202,7 +1202,7 @@ parse_direct_abstract_declarator(scc_parser_t *parser,
|
|||||||
scc_ast_qual_type_t **delay_pointee_ptr) {
|
scc_ast_qual_type_t **delay_pointee_ptr) {
|
||||||
const scc_lexer_tok_t *tok_ptr = nullptr;
|
const scc_lexer_tok_t *tok_ptr = nullptr;
|
||||||
scc_ast_qual_type_t *ret = nullptr;
|
scc_ast_qual_type_t *ret = nullptr;
|
||||||
scc_ast_canon_type_t *canon = scc_ast_ctx_alloc_type(parser->ast_ctx);
|
scc_ast_canon_type_t *canon = scc_ast_module_alloc_type(parser->ast_module);
|
||||||
// direct-abstract-declarator
|
// direct-abstract-declarator
|
||||||
tok_ptr = scc_parser_peek(parser);
|
tok_ptr = scc_parser_peek(parser);
|
||||||
if (tok_ptr == nullptr) {
|
if (tok_ptr == nullptr) {
|
||||||
@@ -1216,7 +1216,7 @@ parse_direct_abstract_declarator(scc_parser_t *parser,
|
|||||||
if (parse_function_parameters_start(parser)) {
|
if (parse_function_parameters_start(parser)) {
|
||||||
scc_ast_decl_vec_t params;
|
scc_ast_decl_vec_t params;
|
||||||
parse_function_parameters(parser, ¶ms);
|
parse_function_parameters(parser, ¶ms);
|
||||||
ret = SCC_AST_ALLOC_QUAL_TYPE(parser->ast_ctx);
|
ret = SCC_AST_ALLOC_QUAL_TYPE(parser->ast_module);
|
||||||
// FIXME
|
// FIXME
|
||||||
scc_ast_type_function_init(ret, canon, base, ¶ms,
|
scc_ast_type_function_init(ret, canon, base, ¶ms,
|
||||||
base->base.loc);
|
base->base.loc);
|
||||||
@@ -1237,7 +1237,7 @@ parse_direct_abstract_declarator(scc_parser_t *parser,
|
|||||||
} else if (tok_ptr->type == SCC_TOK_L_BRACKET) {
|
} else if (tok_ptr->type == SCC_TOK_L_BRACKET) {
|
||||||
// [] SCC_TOK_L_BRACKET
|
// [] SCC_TOK_L_BRACKET
|
||||||
scc_ast_expr_t *size = parse_array_size_type(parser);
|
scc_ast_expr_t *size = parse_array_size_type(parser);
|
||||||
scc_ast_qual_type_t *ret = SCC_AST_ALLOC_QUAL_TYPE(parser->ast_ctx);
|
scc_ast_qual_type_t *ret = SCC_AST_ALLOC_QUAL_TYPE(parser->ast_module);
|
||||||
base =
|
base =
|
||||||
parse_direct_abstract_declarator(parser, base, delay_pointee_ptr);
|
parse_direct_abstract_declarator(parser, base, delay_pointee_ptr);
|
||||||
// FIXME
|
// FIXME
|
||||||
@@ -1254,14 +1254,14 @@ scc_ast_decl_t *scc_parse_declarator(scc_parser_t *parser,
|
|||||||
scc_ast_qual_type_t *decl_type =
|
scc_ast_qual_type_t *decl_type =
|
||||||
parse_declarator(parser, type, nullptr, &decl_name_tok);
|
parse_declarator(parser, type, nullptr, &decl_name_tok);
|
||||||
scc_ast_decl_t *decl = nullptr;
|
scc_ast_decl_t *decl = nullptr;
|
||||||
decl = SCC_AST_ALLOC_DECL(parser->ast_ctx);
|
decl = SCC_AST_ALLOC_DECL(parser->ast_module);
|
||||||
Assert(decl != nullptr);
|
Assert(decl != nullptr);
|
||||||
Assert(decl_name_tok.type == SCC_TOK_IDENT ||
|
Assert(decl_name_tok.type == SCC_TOK_IDENT ||
|
||||||
decl_name_tok.type == SCC_TOK_UNKNOWN);
|
decl_name_tok.type == SCC_TOK_UNKNOWN);
|
||||||
|
|
||||||
// FIXME memory leak
|
// FIXME memory leak
|
||||||
const char *name = decl_name_tok.type == SCC_TOK_IDENT
|
const char *name = decl_name_tok.type == SCC_TOK_IDENT
|
||||||
? scc_str_as_cstr(&decl_name_tok.lexeme)
|
? scc_ast_module_intern(parser->ast_module, scc_str_as_cstr(&decl_name_tok.lexeme))
|
||||||
: nullptr;
|
: nullptr;
|
||||||
|
|
||||||
if (decl_type->base.type == SCC_AST_TYPE_FUNCTION) {
|
if (decl_type->base.type == SCC_AST_TYPE_FUNCTION) {
|
||||||
@@ -1288,7 +1288,7 @@ scc_ast_decl_t *scc_parse_declarator(scc_parser_t *parser,
|
|||||||
// decl = scc_ast_canon_type(decl_type)->record.decl;
|
// decl = scc_ast_canon_type(decl_type)->record.decl;
|
||||||
// } else {
|
// } else {
|
||||||
// // TODO();
|
// // TODO();
|
||||||
// // decl = SCC_AST_ALLOC_DECL(parser->ast_ctx);
|
// // decl = SCC_AST_ALLOC_DECL(parser->ast_module);
|
||||||
// // scc_ast_decl_unsafe_val_init(decl, type, nullptr, nullptr,
|
// // scc_ast_decl_unsafe_val_init(decl, type, nullptr, nullptr,
|
||||||
// // decl_type->base.loc);
|
// // decl_type->base.loc);
|
||||||
// }
|
// }
|
||||||
|
|||||||
@@ -20,10 +20,10 @@ static scc_ast_qual_type_t *dummy_got_type_callback(scc_sema_ctx_t *context,
|
|||||||
assigned_val = value ? value : default
|
assigned_val = value ? value : default
|
||||||
|
|
||||||
void scc_parser_init(scc_parser_t *parser, scc_lexer_tok_ring_t *tok_ring,
|
void scc_parser_init(scc_parser_t *parser, scc_lexer_tok_ring_t *tok_ring,
|
||||||
scc_ast_ctx_t *ast_ctx, scc_sema_ctx_t *sema_ctx) {
|
scc_ast_module_t *ast_module, scc_sema_ctx_t *sema_ctx) {
|
||||||
Assert(parser != nullptr && tok_ring != nullptr);
|
Assert(parser != nullptr && tok_ring != nullptr);
|
||||||
Assert(ast_ctx != nullptr);
|
Assert(ast_module != nullptr);
|
||||||
parser->ast_ctx = ast_ctx;
|
parser->ast_module = ast_module;
|
||||||
|
|
||||||
parser->ring = tok_ring;
|
parser->ring = tok_ring;
|
||||||
parser->errcode = 0;
|
parser->errcode = 0;
|
||||||
|
|||||||
@@ -31,14 +31,15 @@ static void symtab_add_symbol(scc_sema_symtab_t *sema_symtab,
|
|||||||
|
|
||||||
if (decl->name == nullptr)
|
if (decl->name == nullptr)
|
||||||
return;
|
return;
|
||||||
// FIXME memory leak
|
|
||||||
scc_str_t name = scc_str_empty();
|
scc_str_t name = scc_str_empty();
|
||||||
gen_symbol_name(decl, &name);
|
gen_symbol_name(decl, &name);
|
||||||
if (scc_str_is_empty(&name)) {
|
if (scc_str_is_empty(&name)) {
|
||||||
scc_sema_symtab_add_symbol(sema_symtab, decl->name, ast_node_ref);
|
scc_sema_symtab_add_symbol(sema_symtab, decl->name, ast_node_ref);
|
||||||
} else {
|
} else {
|
||||||
scc_sema_symtab_add_symbol(sema_symtab, scc_str_as_cstr(&name),
|
const char *pooled = scc_strpool_intern(&sema_symtab->name_pool,
|
||||||
ast_node_ref);
|
scc_str_as_cstr(&name));
|
||||||
|
scc_sema_symtab_add_symbol(sema_symtab, pooled, ast_node_ref);
|
||||||
|
scc_str_drop(&name);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -291,8 +292,8 @@ static scc_ast_qual_type_t *got_type_callback(scc_sema_ctx_t *sema_ctx,
|
|||||||
return nullptr;
|
return nullptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
void scc_sema_init(scc_sema_ctx_t *sema_ctx, scc_ast_ctx_t *ast_ctx) {
|
void scc_sema_init(scc_sema_ctx_t *sema_ctx, scc_ast_module_t *ast_module) {
|
||||||
sema_ctx->ast_ctx = ast_ctx;
|
sema_ctx->ast_module = ast_module;
|
||||||
scc_sema_symtab_t *sema_symtab = scc_malloc(sizeof(scc_sema_symtab_t));
|
scc_sema_symtab_t *sema_symtab = scc_malloc(sizeof(scc_sema_symtab_t));
|
||||||
if (sema_symtab == nullptr) {
|
if (sema_symtab == nullptr) {
|
||||||
LOG_FATAL("out of memory");
|
LOG_FATAL("out of memory");
|
||||||
@@ -311,25 +312,23 @@ void scc_sema_init(scc_sema_ctx_t *sema_ctx, scc_ast_ctx_t *ast_ctx) {
|
|||||||
scc_vec_init(sema_ctx->break_stack);
|
scc_vec_init(sema_ctx->break_stack);
|
||||||
scc_vec_init(sema_ctx->continue_stack);
|
scc_vec_init(sema_ctx->continue_stack);
|
||||||
|
|
||||||
// FIXME memory leak
|
scc_ast_qual_type_t *type = SCC_AST_ALLOC_QUAL_TYPE(sema_ctx->ast_module);
|
||||||
|
scc_ast_type_builtin_init(type, sema_ctx->ast_module,
|
||||||
scc_ast_qual_type_t *type = SCC_AST_ALLOC_QUAL_TYPE(sema_ctx->ast_ctx);
|
|
||||||
scc_ast_type_builtin_init(type, sema_ctx->ast_ctx,
|
|
||||||
SCC_AST_BUILTIN_TYPE_VA_LIST, scc_pos_create());
|
SCC_AST_BUILTIN_TYPE_VA_LIST, scc_pos_create());
|
||||||
scc_sema_symtab_add_symbol(sema_symtab, "__scc_builtin_va_list",
|
scc_sema_symtab_add_symbol(sema_symtab, "__scc_builtin_va_list",
|
||||||
&type->base);
|
&type->base);
|
||||||
|
|
||||||
scc_ast_decl_t *decl = SCC_AST_ALLOC_DECL(sema_ctx->ast_ctx);
|
scc_ast_decl_t *decl = SCC_AST_ALLOC_DECL(sema_ctx->ast_module);
|
||||||
scc_ast_decl_val_init(decl, type, "__scc_builtin__", nullptr,
|
scc_ast_decl_val_init(decl, type, "__scc_builtin__", nullptr,
|
||||||
scc_pos_create());
|
scc_pos_create());
|
||||||
scc_sema_symtab_add_symbol(sema_symtab, "__func__", &decl->base);
|
scc_sema_symtab_add_symbol(sema_symtab, "__func__", &decl->base);
|
||||||
|
|
||||||
scc_ast_qual_type_t *built_func_type =
|
scc_ast_qual_type_t *built_func_type =
|
||||||
SCC_AST_ALLOC_QUAL_TYPE(sema_ctx->ast_ctx);
|
SCC_AST_ALLOC_QUAL_TYPE(sema_ctx->ast_module);
|
||||||
// FIXME hack
|
// FIXME hack
|
||||||
built_func_type->base.type = SCC_AST_TYPE_FUNCTION;
|
built_func_type->base.type = SCC_AST_TYPE_FUNCTION;
|
||||||
|
|
||||||
scc_ast_decl_t *builin_func = SCC_AST_ALLOC_DECL(sema_ctx->ast_ctx);
|
scc_ast_decl_t *builin_func = SCC_AST_ALLOC_DECL(sema_ctx->ast_module);
|
||||||
scc_ast_decl_func_init(builin_func, built_func_type, "__scc_builtin_func",
|
scc_ast_decl_func_init(builin_func, built_func_type, "__scc_builtin_func",
|
||||||
nullptr, scc_pos_create());
|
nullptr, scc_pos_create());
|
||||||
scc_sema_symtab_add_symbol(sema_symtab, "__scc_builtin_va_start",
|
scc_sema_symtab_add_symbol(sema_symtab, "__scc_builtin_va_start",
|
||||||
@@ -348,8 +347,9 @@ void scc_sema_drop(scc_sema_ctx_t *sema_ctx) {
|
|||||||
scc_vec_free(sema_ctx->break_stack);
|
scc_vec_free(sema_ctx->break_stack);
|
||||||
scc_vec_free(sema_ctx->continue_stack);
|
scc_vec_free(sema_ctx->continue_stack);
|
||||||
|
|
||||||
// FIXME drop obj
|
|
||||||
if (sema_ctx->context) {
|
if (sema_ctx->context) {
|
||||||
scc_sema_symtab_drop(sema_ctx->context);
|
scc_sema_symtab_drop(sema_ctx->context);
|
||||||
|
scc_free(sema_ctx->context);
|
||||||
|
sema_ctx->context = nullptr;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -5,13 +5,19 @@ void scc_sema_symtab_init(scc_sema_symtab_t *symtab) {
|
|||||||
|
|
||||||
scc_hashtable_cstr_init(&symtab->root_scope.symbols);
|
scc_hashtable_cstr_init(&symtab->root_scope.symbols);
|
||||||
symtab->current_scope = &symtab->root_scope;
|
symtab->current_scope = &symtab->root_scope;
|
||||||
|
scc_strpool_init(&symtab->name_pool);
|
||||||
}
|
}
|
||||||
|
|
||||||
void scc_sema_symtab_drop(scc_sema_symtab_t *symtab) {
|
void scc_sema_symtab_drop(scc_sema_symtab_t *symtab) {
|
||||||
while (symtab->current_scope != nullptr) {
|
while (symtab->current_scope != nullptr) {
|
||||||
scc_hashtable_drop(&symtab->current_scope->symbols);
|
scc_hashtable_drop(&symtab->current_scope->symbols);
|
||||||
|
scc_sema_scope_t *scope = symtab->current_scope;
|
||||||
symtab->current_scope = symtab->current_scope->parent;
|
symtab->current_scope = symtab->current_scope->parent;
|
||||||
|
if (scope != &symtab->root_scope) {
|
||||||
|
scc_free(scope);
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
scc_strpool_drop(&symtab->name_pool);
|
||||||
}
|
}
|
||||||
|
|
||||||
void scc_sema_symtab_enter_scope(scc_sema_symtab_t *symtab) {
|
void scc_sema_symtab_enter_scope(scc_sema_symtab_t *symtab) {
|
||||||
@@ -30,8 +36,10 @@ void scc_sema_symtab_leave_scope(scc_sema_symtab_t *symtab) {
|
|||||||
LOG_ERROR("out of scope");
|
LOG_ERROR("out of scope");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
scc_hashtable_drop(&symtab->current_scope->symbols);
|
scc_sema_scope_t *scope = symtab->current_scope;
|
||||||
|
scc_hashtable_drop(&scope->symbols);
|
||||||
symtab->current_scope = symtab->current_scope->parent;
|
symtab->current_scope = symtab->current_scope->parent;
|
||||||
|
scc_free(scope);
|
||||||
}
|
}
|
||||||
|
|
||||||
scc_ast_node_t *scc_sema_symtab_add_symbol(scc_sema_symtab_t *symtab,
|
scc_ast_node_t *scc_sema_symtab_add_symbol(scc_sema_symtab_t *symtab,
|
||||||
|
|||||||
@@ -1,5 +1,6 @@
|
|||||||
#include <pproc_expand.h>
|
#include <pproc_expand.h>
|
||||||
#include <scc_core_ring.h>
|
#include <scc_core_ring.h>
|
||||||
|
#include <scc_path.h>
|
||||||
#include <scc_pproc.h>
|
#include <scc_pproc.h>
|
||||||
|
|
||||||
static int switch_file_stack(scc_pproc_t *pp, scc_str_t *fname, scc_pos_t *pos,
|
static int switch_file_stack(scc_pproc_t *pp, scc_str_t *fname, scc_pos_t *pos,
|
||||||
@@ -100,6 +101,19 @@ void scc_pproc_parse_include(scc_pproc_t *pp, scc_lexer_tok_t *include_tok,
|
|||||||
scc_str_append_ch(&fname, includename[i]);
|
scc_str_append_ch(&fname, includename[i]);
|
||||||
}
|
}
|
||||||
int is_system = includename[0] == '<';
|
int is_system = includename[0] == '<';
|
||||||
|
|
||||||
|
/* 安全检查:拒绝绝对路径和路径穿越 */
|
||||||
|
const char *fname_cstr = scc_str_as_cstr(&fname);
|
||||||
|
if (scc_path_check_include_safe(fname_cstr) != 0) {
|
||||||
|
SCC_ERROR(pos,
|
||||||
|
"unsafe include filename: '%s' (absolute path and '..' "
|
||||||
|
"are not allowed)",
|
||||||
|
fname_cstr);
|
||||||
|
scc_str_drop(&line);
|
||||||
|
scc_str_drop(&fname);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
if (switch_file_stack(pp, &fname, &pos, is_system)) {
|
if (switch_file_stack(pp, &fname, &pos, is_system)) {
|
||||||
// LOG_ERROR()
|
// LOG_ERROR()
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -6,6 +6,7 @@
|
|||||||
typedef struct {
|
typedef struct {
|
||||||
scc_hashtable_t str2libsym;
|
scc_hashtable_t str2libsym;
|
||||||
scc_pe_idata_lib_vec_t idata_libs;
|
scc_pe_idata_lib_vec_t idata_libs;
|
||||||
|
scc_strpool_t pool; /* owns all interned symbol names and library names */
|
||||||
const char *find_path;
|
const char *find_path;
|
||||||
} pe_idata_lib_ctx_t;
|
} pe_idata_lib_ctx_t;
|
||||||
|
|
||||||
@@ -24,11 +25,18 @@ static void load_from_def(pe_idata_lib_ctx_t *ctx, const char *file_path,
|
|||||||
const char *fname = scc_str_as_cstr(&fpath);
|
const char *fname = scc_str_as_cstr(&fpath);
|
||||||
scc_file_t fp = scc_fopen(fname, SCC_FILE_READ);
|
scc_file_t fp = scc_fopen(fname, SCC_FILE_READ);
|
||||||
if (fp == nullptr) {
|
if (fp == nullptr) {
|
||||||
|
scc_str_drop(&fpath);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
LOG_TRACE("load_from_def file read sucessful: %s", fname);
|
LOG_TRACE("load_from_def file read sucessful: %s", fname);
|
||||||
|
|
||||||
usize fsize = scc_fsize(fp);
|
usize fsize = scc_fsize(fp);
|
||||||
|
if (fsize == 0) {
|
||||||
|
scc_fclose(fp);
|
||||||
|
scc_str_drop(&fpath);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
char *buffer = scc_malloc(fsize);
|
char *buffer = scc_malloc(fsize);
|
||||||
Assert(buffer != nullptr);
|
Assert(buffer != nullptr);
|
||||||
|
|
||||||
@@ -36,10 +44,9 @@ static void load_from_def(pe_idata_lib_ctx_t *ctx, const char *file_path,
|
|||||||
Assert(read_size == fsize);
|
Assert(read_size == fsize);
|
||||||
scc_fclose(fp);
|
scc_fclose(fp);
|
||||||
|
|
||||||
// scc_pe_name_vec_t symbol_names;
|
|
||||||
usize line = 0;
|
usize line = 0;
|
||||||
// FIXME
|
|
||||||
buffer[fsize - 1] = '\0';
|
buffer[fsize - 1] = '\0';
|
||||||
|
const char *dll_pooled = scc_strpool_intern(&ctx->pool, dll_name);
|
||||||
for (usize i = 0; i < fsize; i += 1) {
|
for (usize i = 0; i < fsize; i += 1) {
|
||||||
if (buffer[i] == '\n') {
|
if (buffer[i] == '\n') {
|
||||||
line += 1;
|
line += 1;
|
||||||
@@ -56,15 +63,18 @@ static void load_from_def(pe_idata_lib_ctx_t *ctx, const char *file_path,
|
|||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
// FIXME memory leak
|
const char *sym_pooled = scc_strpool_intern(&ctx->pool, buffer + i);
|
||||||
scc_hashtable_set(&ctx->str2libsym, buffer + i, (void *)dll_name);
|
scc_hashtable_set(&ctx->str2libsym, sym_pooled, (void *)dll_pooled);
|
||||||
}
|
}
|
||||||
|
scc_free(buffer);
|
||||||
|
scc_str_drop(&fpath);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void pe_idata_lib_init(pe_idata_lib_ctx_t *ctx, const char *find_path) {
|
static void pe_idata_lib_init(pe_idata_lib_ctx_t *ctx, const char *find_path) {
|
||||||
// Got .dll.def
|
// Got .dll.def
|
||||||
|
|
||||||
scc_hashtable_cstr_init(&ctx->str2libsym);
|
scc_hashtable_cstr_init(&ctx->str2libsym);
|
||||||
|
scc_strpool_init(&ctx->pool);
|
||||||
scc_vec_init(ctx->idata_libs);
|
scc_vec_init(ctx->idata_libs);
|
||||||
ctx->find_path = find_path;
|
ctx->find_path = find_path;
|
||||||
load_from_def(ctx, ctx->find_path, "msvcrt.dll");
|
load_from_def(ctx, ctx->find_path, "msvcrt.dll");
|
||||||
@@ -249,4 +259,12 @@ void sccf2pe(scc_pe_builder_t *builder, const sccf_t *sccf) {
|
|||||||
scc_pe_write_section(builder, &idata_range,
|
scc_pe_write_section(builder, &idata_range,
|
||||||
scc_vec_unsafe_get_data(idata_buffer),
|
scc_vec_unsafe_get_data(idata_buffer),
|
||||||
scc_vec_size(idata_buffer));
|
scc_vec_size(idata_buffer));
|
||||||
|
|
||||||
|
// Cleanup
|
||||||
|
scc_vec_foreach(idata_lib_ctx.idata_libs, i) {
|
||||||
|
scc_vec_free(scc_vec_at(idata_lib_ctx.idata_libs, i).symbol_names);
|
||||||
|
}
|
||||||
|
scc_vec_free(idata_lib_ctx.idata_libs);
|
||||||
|
scc_hashtable_drop(&idata_lib_ctx.str2libsym);
|
||||||
|
scc_strpool_drop(&idata_lib_ctx.pool);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -240,7 +240,14 @@ static inline char *scc_str_move_cstr(scc_str_t *str) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
static inline scc_str_t scc_str_move(scc_str_t *str) {
|
static inline scc_str_t scc_str_move(scc_str_t *str) {
|
||||||
return scc_str_from_cstr(scc_str_move_cstr(str));
|
if (str == nullptr || str->data == nullptr) {
|
||||||
|
return scc_str_empty();
|
||||||
|
}
|
||||||
|
scc_str_t result = *str;
|
||||||
|
str->data = nullptr;
|
||||||
|
str->cap = 0;
|
||||||
|
str->size = 0;
|
||||||
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
#endif /* __SCC_CORE_STR_H__ */
|
#endif /* __SCC_CORE_STR_H__ */
|
||||||
|
|||||||
@@ -106,7 +106,7 @@ typedef size_t usize;
|
|||||||
#define scc_vec_push(vec, value) \
|
#define scc_vec_push(vec, value) \
|
||||||
do { \
|
do { \
|
||||||
if ((vec).size >= (vec).cap) { \
|
if ((vec).size >= (vec).cap) { \
|
||||||
int cap = (vec).cap ? (vec).cap * 2 : 4; \
|
usize cap = (vec).cap ? (vec).cap * 2 : 4; \
|
||||||
scc_vec_realloc(vec, cap); \
|
scc_vec_realloc(vec, cap); \
|
||||||
} \
|
} \
|
||||||
Assert((vec).data != nullptr); \
|
Assert((vec).data != nullptr); \
|
||||||
|
|||||||
@@ -42,12 +42,13 @@ usize scc_fread(scc_file_t file, void *buffer, usize size) {
|
|||||||
usize scc_fwrite(scc_file_t file, const void *buf, usize size) {
|
usize scc_fwrite(scc_file_t file, const void *buf, usize size) {
|
||||||
if (file == scc_stdout) {
|
if (file == scc_stdout) {
|
||||||
scc_pal_write(buf, size);
|
scc_pal_write(buf, size);
|
||||||
|
return size;
|
||||||
} else if (file == scc_stderr) {
|
} else if (file == scc_stderr) {
|
||||||
scc_pal_ewrite(buf, size);
|
scc_pal_ewrite(buf, size);
|
||||||
|
return size;
|
||||||
} else {
|
} else {
|
||||||
return scc_pal_fwrite(file, buf, size);
|
return scc_pal_fwrite(file, buf, size);
|
||||||
}
|
}
|
||||||
return 0;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
cbool scc_fexists(const char *path) {
|
cbool scc_fexists(const char *path) {
|
||||||
|
|||||||
30
runtime/scc_utils/include/scc_path.h
Normal file
30
runtime/scc_utils/include/scc_path.h
Normal file
@@ -0,0 +1,30 @@
|
|||||||
|
#ifndef __SCC_PATH_H__
|
||||||
|
#define __SCC_PATH_H__
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief 检查路径是否为绝对路径
|
||||||
|
* @param path 要检查的路径
|
||||||
|
* @return 1 是绝对路径, 0 不是
|
||||||
|
*/
|
||||||
|
int scc_path_is_absolute(const char *path);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief 检查路径是否包含 .. 路径穿越组件
|
||||||
|
* @param path 要检查的路径
|
||||||
|
* @return 1 包含 .., 0 不包含
|
||||||
|
*/
|
||||||
|
int scc_path_has_dotdot(const char *path);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief 检查路径是否安全用作 #include 文件名
|
||||||
|
*
|
||||||
|
* 拒绝条件:
|
||||||
|
* - 绝对路径(以 / \ 开头,或 Windows 驱动符如 C:\)
|
||||||
|
* - 包含 .. 路径穿越组件
|
||||||
|
*
|
||||||
|
* @param path 要检查的路径
|
||||||
|
* @return 0 安全, -1 不安全
|
||||||
|
*/
|
||||||
|
int scc_path_check_include_safe(const char *path);
|
||||||
|
|
||||||
|
#endif /* __SCC_PATH_H__ */
|
||||||
@@ -4,6 +4,7 @@
|
|||||||
// #include "kllist.h"
|
// #include "kllist.h"
|
||||||
#include "scc_hashtable.h"
|
#include "scc_hashtable.h"
|
||||||
#include "scc_strpool.h"
|
#include "scc_strpool.h"
|
||||||
|
#include "scc_path.h"
|
||||||
#include <scc_core.h>
|
#include <scc_core.h>
|
||||||
|
|
||||||
#endif /* __SMCC_UTILS_H__ */
|
#endif /* __SMCC_UTILS_H__ */
|
||||||
|
|||||||
@@ -44,13 +44,15 @@ void scc_hashtable_usize_init(scc_hashtable_t *ht) {
|
|||||||
scc_hashtable_init(ht, ht_usizehash, ht_usizecmp, nullptr);
|
scc_hashtable_init(ht, ht_usizehash, ht_usizecmp, nullptr);
|
||||||
}
|
}
|
||||||
|
|
||||||
static int next_power_of_two(int n) {
|
static usize next_power_of_two(usize n) {
|
||||||
|
if (n == 0) return 32;
|
||||||
n--;
|
n--;
|
||||||
n |= n >> 1;
|
n |= n >> 1;
|
||||||
n |= n >> 2;
|
n |= n >> 2;
|
||||||
n |= n >> 4;
|
n |= n >> 4;
|
||||||
n |= n >> 8;
|
n |= n >> 8;
|
||||||
n |= n >> 16;
|
n |= n >> 16;
|
||||||
|
n |= n >> 32;
|
||||||
return n + 1;
|
return n + 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -119,7 +121,7 @@ static void adjust_capacity(scc_hashtable_t *ht, usize new_cap) {
|
|||||||
|
|
||||||
void *scc_hashtable_set(scc_hashtable_t *ht, const void *key, void *value) {
|
void *scc_hashtable_set(scc_hashtable_t *ht, const void *key, void *value) {
|
||||||
if (ht->count + ht->tombstone_count >= ht->entries.cap * 0.75) {
|
if (ht->count + ht->tombstone_count >= ht->entries.cap * 0.75) {
|
||||||
int new_cap = ht->entries.cap < SCC_INIT_HASHMAP_SIZE
|
usize new_cap = ht->entries.cap < SCC_INIT_HASHMAP_SIZE
|
||||||
? SCC_INIT_HASHMAP_SIZE
|
? SCC_INIT_HASHMAP_SIZE
|
||||||
: ht->entries.cap * 2;
|
: ht->entries.cap * 2;
|
||||||
adjust_capacity(ht, new_cap);
|
adjust_capacity(ht, new_cap);
|
||||||
@@ -127,6 +129,10 @@ void *scc_hashtable_set(scc_hashtable_t *ht, const void *key, void *value) {
|
|||||||
|
|
||||||
u32 hash = ht->hash_func(key, ht->userdata);
|
u32 hash = ht->hash_func(key, ht->userdata);
|
||||||
scc_hashtable_entry_t *entry = find_entry(ht, key, hash);
|
scc_hashtable_entry_t *entry = find_entry(ht, key, hash);
|
||||||
|
if (entry == nullptr) {
|
||||||
|
LOG_FATAL("scc_hashtable_set: hash table is full");
|
||||||
|
return nullptr;
|
||||||
|
}
|
||||||
|
|
||||||
void *old_value = nullptr;
|
void *old_value = nullptr;
|
||||||
if (entry->state == ENTRY_ACTIVE) {
|
if (entry->state == ENTRY_ACTIVE) {
|
||||||
|
|||||||
67
runtime/scc_utils/src/scc_path.c
Normal file
67
runtime/scc_utils/src/scc_path.c
Normal file
@@ -0,0 +1,67 @@
|
|||||||
|
#include <scc_core.h>
|
||||||
|
#include <scc_path.h>
|
||||||
|
|
||||||
|
#ifdef _WIN32
|
||||||
|
#define SCC_PATH_SEP_A '\\'
|
||||||
|
#define SCC_PATH_SEP_B '/'
|
||||||
|
#define SCC_IS_DRIVE_LETTER(c) \
|
||||||
|
(((c) >= 'a' && (c) <= 'z') || ((c) >= 'A' && (c) <= 'Z'))
|
||||||
|
#else
|
||||||
|
#define SCC_PATH_SEP_A '/'
|
||||||
|
#define SCC_PATH_SEP_B '/' /* no alternative separator on non-Windows */
|
||||||
|
#endif
|
||||||
|
|
||||||
|
int scc_path_is_absolute(const char *path) {
|
||||||
|
if (path == nullptr || path[0] == '\0')
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
/* Unix absolute: /path */
|
||||||
|
if (path[0] == '/')
|
||||||
|
return 1;
|
||||||
|
|
||||||
|
#ifdef _WIN32
|
||||||
|
/* Windows absolute: C:\path or \path */
|
||||||
|
if (path[0] == '\\')
|
||||||
|
return 1;
|
||||||
|
if (SCC_IS_DRIVE_LETTER(path[0]) && path[1] == ':')
|
||||||
|
return 1;
|
||||||
|
#endif
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
int scc_path_has_dotdot(const char *path) {
|
||||||
|
if (path == nullptr)
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
const char *p = path;
|
||||||
|
while (*p) {
|
||||||
|
/* Look for '.' followed by '.' */
|
||||||
|
if (p[0] == '.' && p[1] == '.') {
|
||||||
|
char next = p[2];
|
||||||
|
/* ".." at end of string or followed by a separator */
|
||||||
|
if (next == '\0' || next == SCC_PATH_SEP_A || next == SCC_PATH_SEP_B) {
|
||||||
|
/* Must also check that this ".." is at start or preceded by a separator */
|
||||||
|
if (p == path ||
|
||||||
|
p[-1] == SCC_PATH_SEP_A || p[-1] == SCC_PATH_SEP_B) {
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
p++;
|
||||||
|
}
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
int scc_path_check_include_safe(const char *path) {
|
||||||
|
if (path == nullptr || path[0] == '\0')
|
||||||
|
return -1;
|
||||||
|
|
||||||
|
if (scc_path_is_absolute(path))
|
||||||
|
return -1;
|
||||||
|
|
||||||
|
if (scc_path_has_dotdot(path))
|
||||||
|
return -1;
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
@@ -22,7 +22,16 @@ const char *scc_strpool_intern(scc_strpool_t *pool, const char *str) {
|
|||||||
return new_str;
|
return new_str;
|
||||||
}
|
}
|
||||||
|
|
||||||
void scc_strpool_drop(scc_strpool_t *pool) { scc_hashtable_drop(&pool->ht); }
|
void scc_strpool_drop(scc_strpool_t *pool) {
|
||||||
|
// Free all interned string allocations before dropping the hash table
|
||||||
|
for (usize i = 0; i < pool->ht.entries.cap; i++) {
|
||||||
|
scc_hashtable_entry_t *entry = &scc_vec_at(pool->ht.entries, i);
|
||||||
|
if (entry->state == ENTRY_ACTIVE) {
|
||||||
|
scc_free((void *)entry->key);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
scc_hashtable_drop(&pool->ht);
|
||||||
|
}
|
||||||
|
|
||||||
void scc_strpool_foreach(scc_strpool_t *pool, scc_strpool_iter_fn iter_func,
|
void scc_strpool_foreach(scc_strpool_t *pool, scc_strpool_iter_fn iter_func,
|
||||||
void *context) {
|
void *context) {
|
||||||
|
|||||||
10
src/main.c
10
src/main.c
@@ -203,11 +203,11 @@ int main(int argc, const char **argv, const char **envp) {
|
|||||||
scc_lexer_tok_ring_t *tok_ring =
|
scc_lexer_tok_ring_t *tok_ring =
|
||||||
scc_pproc_to_ring(&pproc, 1024, false, false);
|
scc_pproc_to_ring(&pproc, 1024, false, false);
|
||||||
scc_parser_t parser;
|
scc_parser_t parser;
|
||||||
scc_ast_ctx_t ast_ctx;
|
scc_ast_module_t ast_module;
|
||||||
scc_ast_ctx_init(&ast_ctx);
|
scc_ast_module_init(&ast_module);
|
||||||
scc_sema_ctx_t sema_ctx;
|
scc_sema_ctx_t sema_ctx;
|
||||||
scc_sema_init(&sema_ctx, &ast_ctx);
|
scc_sema_init(&sema_ctx, &ast_module);
|
||||||
scc_parser_init(&parser, tok_ring, &ast_ctx, &sema_ctx);
|
scc_parser_init(&parser, tok_ring, &ast_module, &sema_ctx);
|
||||||
scc_ast_translation_unit_t *translation_unit =
|
scc_ast_translation_unit_t *translation_unit =
|
||||||
scc_parse_translation_unit(&parser);
|
scc_parse_translation_unit(&parser);
|
||||||
if (parser.errcode != 0) {
|
if (parser.errcode != 0) {
|
||||||
@@ -243,7 +243,7 @@ sstream_drop:
|
|||||||
#include <target/scc_abi_win_x64_pc.h>
|
#include <target/scc_abi_win_x64_pc.h>
|
||||||
scc_hir_cprog_t cprog;
|
scc_hir_cprog_t cprog;
|
||||||
scc_hir_cprog_init(&cprog);
|
scc_hir_cprog_init(&cprog);
|
||||||
scc_ast2ir_ctx_init(&ast2ir_ctx, &scc_ast_abi_impl, &ast_ctx, &cprog);
|
scc_ast2ir_ctx_init(&ast2ir_ctx, &scc_ast_abi_impl, &ast_module, &cprog);
|
||||||
scc_ast2ir_run(&ast2ir_ctx, translation_unit);
|
scc_ast2ir_run(&ast2ir_ctx, translation_unit);
|
||||||
scc_ast2ir_ctx_drop(&ast2ir_ctx);
|
scc_ast2ir_ctx_drop(&ast2ir_ctx);
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user