refactor(log): 统一日志系统并添加链接器实现
- 为所有模块添加统一的 scc_*_log.h 日志头文件,删除旧的 lexer_log.h/c - 将运行时日志从 scc_utils 迁移到 scc_core 目录,统一日志管理 - 在解析器表达式/语句/类型解析中添加 LOG_TRACE 调试日志 - 实现 SCCF 链接器 (sccf_linker) 支持多目标文件链接 - 重构 CLI 主程序 (main.c/config.c),新增 cmd_log.h 调试支持 - 优化 x86 指令编码操作数对齐检查 - 修复预处理器的指令处理和宏展开逻辑
This commit is contained in:
26
libs/ast2ir/include/scc_ast2ir_log.h
Normal file
26
libs/ast2ir/include/scc_ast2ir_log.h
Normal file
@@ -0,0 +1,26 @@
|
|||||||
|
#ifndef __SCC_AST2IR_LOG_H__
|
||||||
|
#define __SCC_AST2IR_LOG_H__
|
||||||
|
|
||||||
|
typedef struct logger logger_t;
|
||||||
|
extern logger_t __scc_ast2ir_log;
|
||||||
|
extern logger_t __scc_ast2ir_user;
|
||||||
|
|
||||||
|
#define SCC_LOG_HANDLER &__scc_ast2ir_user
|
||||||
|
#define LOG_DEFAULT_HANDLER &__scc_ast2ir_log
|
||||||
|
#include <scc_log.h>
|
||||||
|
|
||||||
|
#ifdef __SCC_AST2IR_LOG_IMPL__
|
||||||
|
logger_t __scc_ast2ir_log = {
|
||||||
|
.name = "ast2ir",
|
||||||
|
.level = LOG_LEVEL_ALL,
|
||||||
|
.handler = log_default_handler,
|
||||||
|
};
|
||||||
|
|
||||||
|
logger_t __scc_ast2ir_user = {
|
||||||
|
.name = "ast2ir",
|
||||||
|
.level = LOG_LEVEL_ALL,
|
||||||
|
.user_handler = scc_log_handler,
|
||||||
|
};
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#endif
|
||||||
@@ -1,3 +1,6 @@
|
|||||||
|
#define __SCC_AST2IR_LOG_IMPL__
|
||||||
|
#include <scc_ast2ir_log.h>
|
||||||
|
|
||||||
#include <scc_ast2ir.h>
|
#include <scc_ast2ir.h>
|
||||||
#include <scc_ast_def.h>
|
#include <scc_ast_def.h>
|
||||||
#include <scc_ast_utils.h>
|
#include <scc_ast_utils.h>
|
||||||
@@ -192,6 +195,7 @@ void scc_ast2ir_stmt(scc_ast2ir_ctx_t *ctx, const scc_ast_stmt_t *stmt) {
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
LOG_DEBUG("stmt type=%d", stmt->base.type);
|
||||||
switch (stmt->base.type) {
|
switch (stmt->base.type) {
|
||||||
case SCC_AST_STMT_COMPOUND: {
|
case SCC_AST_STMT_COMPOUND: {
|
||||||
scc_vec_foreach(stmt->compound.block_items, i) {
|
scc_vec_foreach(stmt->compound.block_items, i) {
|
||||||
@@ -542,6 +546,7 @@ void scc_ast2ir_decl(scc_ast2ir_ctx_t *ctx, const scc_ast_decl_t *decl,
|
|||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case SCC_AST_DECL_FUNC: {
|
case SCC_AST_DECL_FUNC: {
|
||||||
|
LOG_DEBUG("function '%s'", decl->name);
|
||||||
scc_hir_type_ref_t func_type_ref =
|
scc_hir_type_ref_t func_type_ref =
|
||||||
scc_ast2ir_type(ctx, decl->func.type);
|
scc_ast2ir_type(ctx, decl->func.type);
|
||||||
scc_hir_func_ref_t func_ref =
|
scc_hir_func_ref_t func_ref =
|
||||||
@@ -674,6 +679,8 @@ void scc_ast2ir_run(scc_ast2ir_ctx_t *ctx,
|
|||||||
const scc_ast_translation_unit_t *tu) {
|
const scc_ast_translation_unit_t *tu) {
|
||||||
Assert(ctx != nullptr && tu != nullptr);
|
Assert(ctx != nullptr && tu != nullptr);
|
||||||
|
|
||||||
|
LOG_INFO("translating %zu declaration(s) to HIR",
|
||||||
|
scc_vec_size(tu->declarations));
|
||||||
scc_vec_foreach(tu->declarations, i) {
|
scc_vec_foreach(tu->declarations, i) {
|
||||||
scc_ast_decl_t *decl = scc_vec_at(tu->declarations, i);
|
scc_ast_decl_t *decl = scc_vec_at(tu->declarations, i);
|
||||||
scc_ast2ir_decl(ctx, decl, true);
|
scc_ast2ir_decl(ctx, decl, true);
|
||||||
|
|||||||
@@ -1,3 +1,5 @@
|
|||||||
|
#include <scc_ast2ir_log.h>
|
||||||
|
|
||||||
#include <scc_ast2ir.h>
|
#include <scc_ast2ir.h>
|
||||||
#include <scc_ast_def.h>
|
#include <scc_ast_def.h>
|
||||||
#include <scc_ast_utils.h>
|
#include <scc_ast_utils.h>
|
||||||
@@ -158,9 +160,11 @@ scc_hir_value_ref_t scc_ast2ir_expr(scc_ast2ir_ctx_t *ctx,
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
LOG_DEBUG("expr type=%d is_lvalue=%d", expr->base.type, (int)is_lvalue);
|
||||||
cbool is_assign = true;
|
cbool is_assign = true;
|
||||||
switch (expr->base.type) {
|
switch (expr->base.type) {
|
||||||
case SCC_AST_EXPR_BINARY: {
|
case SCC_AST_EXPR_BINARY: {
|
||||||
|
LOG_DEBUG(" binary op=%d", expr->binary.op);
|
||||||
scc_ast_expr_t tmp_expr;
|
scc_ast_expr_t tmp_expr;
|
||||||
scc_hir_value_ref_t lhs = SCC_HIR_REF_nullptr,
|
scc_hir_value_ref_t lhs = SCC_HIR_REF_nullptr,
|
||||||
rhs = SCC_HIR_REF_nullptr;
|
rhs = SCC_HIR_REF_nullptr;
|
||||||
@@ -365,6 +369,7 @@ scc_hir_value_ref_t scc_ast2ir_expr(scc_ast2ir_ctx_t *ctx,
|
|||||||
return scc_hir_builder_binop(&ctx->builder, op, lhs, rhs);
|
return scc_hir_builder_binop(&ctx->builder, op, lhs, rhs);
|
||||||
} break;
|
} break;
|
||||||
case SCC_AST_EXPR_UNARY: {
|
case SCC_AST_EXPR_UNARY: {
|
||||||
|
LOG_DEBUG(" unary op=%d", expr->unary.op);
|
||||||
if (expr->unary.op == SCC_AST_OP_ADDRESS_OF) {
|
if (expr->unary.op == SCC_AST_OP_ADDRESS_OF) {
|
||||||
return scc_ast2ir_expr(ctx, expr->unary.operand, true);
|
return scc_ast2ir_expr(ctx, expr->unary.operand, true);
|
||||||
} else if (expr->unary.op == SCC_AST_OP_INDIRECTION) {
|
} else if (expr->unary.op == SCC_AST_OP_INDIRECTION) {
|
||||||
@@ -508,6 +513,7 @@ scc_hir_value_ref_t scc_ast2ir_expr(scc_ast2ir_ctx_t *ctx,
|
|||||||
UNREACHABLE();
|
UNREACHABLE();
|
||||||
} break;
|
} break;
|
||||||
case SCC_AST_EXPR_COND: {
|
case SCC_AST_EXPR_COND: {
|
||||||
|
LOG_DEBUG(" ternary conditional");
|
||||||
scc_hir_type_ref_t true_type = SCC_HIR_REF_nullptr;
|
scc_hir_type_ref_t true_type = SCC_HIR_REF_nullptr;
|
||||||
scc_hir_type_ref_t false_type = SCC_HIR_REF_nullptr;
|
scc_hir_type_ref_t false_type = SCC_HIR_REF_nullptr;
|
||||||
|
|
||||||
@@ -559,7 +565,10 @@ scc_hir_value_ref_t scc_ast2ir_expr(scc_ast2ir_ctx_t *ctx,
|
|||||||
return scc_hir_builder_load(&ctx->builder, result_slot);
|
return scc_hir_builder_load(&ctx->builder, result_slot);
|
||||||
} break;
|
} break;
|
||||||
case SCC_AST_EXPR_CALL: {
|
case SCC_AST_EXPR_CALL: {
|
||||||
// 转换参数
|
LOG_DEBUG(" call '%s'",
|
||||||
|
expr->call.callee->identifier._target
|
||||||
|
? expr->call.callee->identifier._target->name
|
||||||
|
: "?");
|
||||||
scc_hir_value_ref_vec_t args;
|
scc_hir_value_ref_vec_t args;
|
||||||
scc_vec_init(args);
|
scc_vec_init(args);
|
||||||
|
|
||||||
@@ -640,7 +649,7 @@ scc_hir_value_ref_t scc_ast2ir_expr(scc_ast2ir_ctx_t *ctx,
|
|||||||
return node;
|
return node;
|
||||||
}
|
}
|
||||||
case SCC_AST_EXPR_ARRAY_SUBSCRIPT: {
|
case SCC_AST_EXPR_ARRAY_SUBSCRIPT: {
|
||||||
// 1. 计算数组/指针基址(右值,得到地址)
|
LOG_DEBUG(" array subscript");
|
||||||
scc_hir_value_ref_t base_ptr =
|
scc_hir_value_ref_t base_ptr =
|
||||||
scc_ast2ir_expr(ctx, expr->subscript.array, true);
|
scc_ast2ir_expr(ctx, expr->subscript.array, true);
|
||||||
// 2. 计算下标值
|
// 2. 计算下标值
|
||||||
@@ -670,7 +679,7 @@ scc_hir_value_ref_t scc_ast2ir_expr(scc_ast2ir_ctx_t *ctx,
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
case SCC_AST_EXPR_MEMBER: {
|
case SCC_AST_EXPR_MEMBER: {
|
||||||
// 1. 获取基对象的左值(地址)
|
LOG_DEBUG(" member access field_idx=%zu", expr->member._target_idx);
|
||||||
scc_hir_value_ref_t base_ptr =
|
scc_hir_value_ref_t base_ptr =
|
||||||
scc_ast2ir_expr(ctx, expr->member.base, true);
|
scc_ast2ir_expr(ctx, expr->member.base, true);
|
||||||
// 2. 通过偏移生成字段地址
|
// 2. 通过偏移生成字段地址
|
||||||
@@ -688,7 +697,7 @@ scc_hir_value_ref_t scc_ast2ir_expr(scc_ast2ir_ctx_t *ctx,
|
|||||||
return scc_hir_builder_load(&ctx->builder, field_ptr);
|
return scc_hir_builder_load(&ctx->builder, field_ptr);
|
||||||
}
|
}
|
||||||
case SCC_AST_EXPR_PTR_MEMBER: {
|
case SCC_AST_EXPR_PTR_MEMBER: {
|
||||||
// 1. 计算指针值(obj->field 等价于 (*obj).field)
|
LOG_DEBUG(" ptr member access");
|
||||||
scc_hir_value_ref_t obj_ptr =
|
scc_hir_value_ref_t obj_ptr =
|
||||||
scc_ast2ir_expr(ctx, expr->member.base, false);
|
scc_ast2ir_expr(ctx, expr->member.base, false);
|
||||||
// 2. 解引用得到对象地址,再访问成员
|
// 2. 解引用得到对象地址,再访问成员
|
||||||
|
|||||||
26
libs/ir/hir/include/scc_hir_log.h
Normal file
26
libs/ir/hir/include/scc_hir_log.h
Normal file
@@ -0,0 +1,26 @@
|
|||||||
|
#ifndef __SCC_HIR_LOG_H__
|
||||||
|
#define __SCC_HIR_LOG_H__
|
||||||
|
|
||||||
|
typedef struct logger logger_t;
|
||||||
|
extern logger_t __scc_hir_log;
|
||||||
|
extern logger_t __scc_hir_user;
|
||||||
|
|
||||||
|
#define SCC_LOG_HANDLER &__scc_hir_user
|
||||||
|
#define LOG_DEFAULT_HANDLER &__scc_hir_log
|
||||||
|
#include <scc_log.h>
|
||||||
|
|
||||||
|
#ifdef __SCC_HIR_LOG_IMPL__
|
||||||
|
logger_t __scc_hir_log = {
|
||||||
|
.name = "hir",
|
||||||
|
.level = LOG_LEVEL_ALL,
|
||||||
|
.handler = log_default_handler,
|
||||||
|
};
|
||||||
|
|
||||||
|
logger_t __scc_hir_user = {
|
||||||
|
.name = "hir",
|
||||||
|
.level = LOG_LEVEL_ALL,
|
||||||
|
.user_handler = scc_log_handler,
|
||||||
|
};
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#endif
|
||||||
@@ -1,3 +1,6 @@
|
|||||||
|
#define __SCC_HIR_LOG_IMPL__
|
||||||
|
#include <scc_hir_log.h>
|
||||||
|
|
||||||
#include <scc_hir.h>
|
#include <scc_hir.h>
|
||||||
|
|
||||||
void scc_hir_type_init(scc_hir_type_t *in, scc_hir_type_tag_t tag) {
|
void scc_hir_type_init(scc_hir_type_t *in, scc_hir_type_tag_t tag) {
|
||||||
|
|||||||
@@ -1,3 +1,5 @@
|
|||||||
|
#include <scc_hir_log.h>
|
||||||
|
|
||||||
#include <scc_hir_builder.h>
|
#include <scc_hir_builder.h>
|
||||||
#include <scc_hir_def.h>
|
#include <scc_hir_def.h>
|
||||||
#include <scc_hir_prog.h>
|
#include <scc_hir_prog.h>
|
||||||
|
|||||||
@@ -1,3 +1,5 @@
|
|||||||
|
#include <scc_hir_log.h>
|
||||||
|
|
||||||
#include <scc_hir_dump.h>
|
#include <scc_hir_dump.h>
|
||||||
#include <scc_hir_prog.h>
|
#include <scc_hir_prog.h>
|
||||||
#include <scc_tree_dump.h>
|
#include <scc_tree_dump.h>
|
||||||
|
|||||||
26
libs/ir/lir/include/scc_lir_log.h
Normal file
26
libs/ir/lir/include/scc_lir_log.h
Normal file
@@ -0,0 +1,26 @@
|
|||||||
|
#ifndef __SCC_LIR_LOG_H__
|
||||||
|
#define __SCC_LIR_LOG_H__
|
||||||
|
|
||||||
|
typedef struct logger logger_t;
|
||||||
|
extern logger_t __scc_lir_log;
|
||||||
|
extern logger_t __scc_lir_user;
|
||||||
|
|
||||||
|
#define SCC_LOG_HANDLER &__scc_lir_user
|
||||||
|
#define LOG_DEFAULT_HANDLER &__scc_lir_log
|
||||||
|
#include <scc_log.h>
|
||||||
|
|
||||||
|
#ifdef __SCC_LIR_LOG_IMPL__
|
||||||
|
logger_t __scc_lir_log = {
|
||||||
|
.name = "lir",
|
||||||
|
.level = LOG_LEVEL_ALL,
|
||||||
|
.handler = log_default_handler,
|
||||||
|
};
|
||||||
|
|
||||||
|
logger_t __scc_lir_user = {
|
||||||
|
.name = "lir",
|
||||||
|
.level = LOG_LEVEL_ALL,
|
||||||
|
.user_handler = scc_log_handler,
|
||||||
|
};
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#endif
|
||||||
@@ -2,6 +2,7 @@
|
|||||||
* @file scc_hir2lir.c
|
* @file scc_hir2lir.c
|
||||||
* @brief 将高级 IR (scc_ir) 降级为低层 LIR (scc_lir)
|
* @brief 将高级 IR (scc_ir) 降级为低层 LIR (scc_lir)
|
||||||
*/
|
*/
|
||||||
|
#include <scc_lir_log.h>
|
||||||
|
|
||||||
#include <scc_hashtable.h>
|
#include <scc_hashtable.h>
|
||||||
#include <scc_hir2lir.h>
|
#include <scc_hir2lir.h>
|
||||||
@@ -323,6 +324,7 @@ static void translate_hir_value(ir2lir_ctx_t *ctx, scc_hir_value_t *value,
|
|||||||
if (scc_hashtable_get(&ctx->value_to_vreg, (void *)(uintptr_t)value_ref))
|
if (scc_hashtable_get(&ctx->value_to_vreg, (void *)(uintptr_t)value_ref))
|
||||||
return;
|
return;
|
||||||
|
|
||||||
|
LOG_TRACE("translate val_ref=%zu tag=%d", (size_t)value_ref, value->tag);
|
||||||
u8 size_bits = 0;
|
u8 size_bits = 0;
|
||||||
scc_lir_ext_t ext = SCC_LIR_EXT_NONE;
|
scc_lir_ext_t ext = SCC_LIR_EXT_NONE;
|
||||||
ir_type_to_lir_size_ext(ctx->hir_module, value->type, &size_bits, &ext);
|
ir_type_to_lir_size_ext(ctx->hir_module, value->type, &size_bits, &ext);
|
||||||
@@ -643,6 +645,9 @@ static void translate_hir_value(ir2lir_ctx_t *ctx, scc_hir_value_t *value,
|
|||||||
|
|
||||||
static void translate_func(ir2lir_ctx_t *ctx, scc_hir_func_t *ir_func) {
|
static void translate_func(ir2lir_ctx_t *ctx, scc_hir_func_t *ir_func) {
|
||||||
scc_hir_func_meta_t *func_meta = SCC_HIR_FUNC_META(ir_func);
|
scc_hir_func_meta_t *func_meta = SCC_HIR_FUNC_META(ir_func);
|
||||||
|
LOG_DEBUG("translate func '%s' (%zu bblocks)",
|
||||||
|
ir_func->name ? ir_func->name : "?",
|
||||||
|
scc_vec_size(ir_func->bblocks));
|
||||||
|
|
||||||
scc_lir_func_meta_t *lir_func_meta =
|
scc_lir_func_meta_t *lir_func_meta =
|
||||||
scc_malloc(sizeof(scc_lir_func_meta_t));
|
scc_malloc(sizeof(scc_lir_func_meta_t));
|
||||||
@@ -689,6 +694,8 @@ static void translate_func(ir2lir_ctx_t *ctx, scc_hir_func_t *ir_func) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
void scc_hir2lir(scc_lir_module_t *module, scc_hir_cprog_t *cprog) {
|
void scc_hir2lir(scc_lir_module_t *module, scc_hir_cprog_t *cprog) {
|
||||||
|
LOG_INFO("HIR -> LIR lowering start (%zu funcs)",
|
||||||
|
scc_vec_size(cprog->func_defs));
|
||||||
Assert(module != nullptr && cprog != nullptr);
|
Assert(module != nullptr && cprog != nullptr);
|
||||||
|
|
||||||
// FIXME
|
// FIXME
|
||||||
|
|||||||
2
libs/ir/lir/src/scc_lir.c
Normal file
2
libs/ir/lir/src/scc_lir.c
Normal file
@@ -0,0 +1,2 @@
|
|||||||
|
#define __SCC_LIR_LOG_IMPL__
|
||||||
|
#include <scc_lir_log.h>
|
||||||
@@ -1,3 +1,5 @@
|
|||||||
|
#include <scc_lir_log.h>
|
||||||
|
|
||||||
#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) {
|
||||||
@@ -13,7 +15,8 @@ void scc_lir_module_drop(scc_lir_module_t *lir_module) {
|
|||||||
scc_lir_symbol_meta_t *meta = lir_module->symbol_metas.data[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 */
|
usize cfg_idx = i + 1; /* cfg_module.symbols[0] is null sentinel */
|
||||||
if (cfg_idx < scc_vec_size(lir_module->cfg_module.symbols)) {
|
if (cfg_idx < scc_vec_size(lir_module->cfg_module.symbols)) {
|
||||||
scc_cfg_symbol_t *sym = &lir_module->cfg_module.symbols.data[cfg_idx];
|
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) {
|
if (sym->kind == SCC_CFG_SYMBOL_KIND_DATA && meta->data.init_data) {
|
||||||
scc_free(meta->data.init_data);
|
scc_free(meta->data.init_data);
|
||||||
}
|
}
|
||||||
|
|||||||
26
libs/ir/mir/include/scc_mir_log.h
Normal file
26
libs/ir/mir/include/scc_mir_log.h
Normal file
@@ -0,0 +1,26 @@
|
|||||||
|
#ifndef __SCC_MIR_LOG_H__
|
||||||
|
#define __SCC_MIR_LOG_H__
|
||||||
|
|
||||||
|
typedef struct logger logger_t;
|
||||||
|
extern logger_t __scc_mir_log;
|
||||||
|
extern logger_t __scc_mir_user;
|
||||||
|
|
||||||
|
#define SCC_LOG_HANDLER &__scc_mir_user
|
||||||
|
#define LOG_DEFAULT_HANDLER &__scc_mir_log
|
||||||
|
#include <scc_log.h>
|
||||||
|
|
||||||
|
#ifdef __SCC_MIR_LOG_IMPL__
|
||||||
|
logger_t __scc_mir_log = {
|
||||||
|
.name = "mir",
|
||||||
|
.level = LOG_LEVEL_ALL,
|
||||||
|
.handler = log_default_handler,
|
||||||
|
};
|
||||||
|
|
||||||
|
logger_t __scc_mir_user = {
|
||||||
|
.name = "mir",
|
||||||
|
.level = LOG_LEVEL_ALL,
|
||||||
|
.user_handler = scc_log_handler,
|
||||||
|
};
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#endif
|
||||||
@@ -1,3 +1,5 @@
|
|||||||
|
#include <scc_mir_log.h>
|
||||||
|
|
||||||
#include <arch/scc_x86_mir.h>
|
#include <arch/scc_x86_mir.h>
|
||||||
|
|
||||||
static inline scc_x86_iform_t
|
static inline scc_x86_iform_t
|
||||||
|
|||||||
@@ -1,9 +1,14 @@
|
|||||||
|
#include <scc_mir_log.h>
|
||||||
|
|
||||||
#include <arch/scc_x86_isel.h>
|
#include <arch/scc_x86_isel.h>
|
||||||
#include <scc_lir2mir.h>
|
#include <scc_lir2mir.h>
|
||||||
|
#include <scc_mir_module.h>
|
||||||
#include <target/scc_win64.h>
|
#include <target/scc_win64.h>
|
||||||
|
|
||||||
void scc_lir2mir(scc_mir_module_t *mir_module,
|
void scc_lir2mir(scc_mir_module_t *mir_module,
|
||||||
const scc_lir_module_t *lir_module) {
|
const scc_lir_module_t *lir_module) {
|
||||||
|
LOG_INFO("LIR -> MIR conversion (%zu funcs)",
|
||||||
|
scc_vec_size(lir_module->cfg_module.funcs));
|
||||||
// Move
|
// Move
|
||||||
mir_module->cfg_module = lir_module->cfg_module;
|
mir_module->cfg_module = lir_module->cfg_module;
|
||||||
|
|
||||||
|
|||||||
@@ -1,3 +1,6 @@
|
|||||||
|
#define __SCC_MIR_LOG_IMPL__
|
||||||
|
#include <scc_mir_log.h>
|
||||||
|
|
||||||
#include <scc_mir.h>
|
#include <scc_mir.h>
|
||||||
|
|
||||||
void scc_mir_func_meta_init(scc_mir_func_meta_t *func_meta) {
|
void scc_mir_func_meta_init(scc_mir_func_meta_t *func_meta) {
|
||||||
|
|||||||
@@ -1,3 +1,5 @@
|
|||||||
|
#include <scc_mir_log.h>
|
||||||
|
|
||||||
#include <arch/scc_x86_mir.h>
|
#include <arch/scc_x86_mir.h>
|
||||||
#include <arch/scc_x86_reg_alloc.h>
|
#include <arch/scc_x86_reg_alloc.h>
|
||||||
#include <target/scc_win64.h>
|
#include <target/scc_win64.h>
|
||||||
@@ -11,17 +13,23 @@
|
|||||||
|
|
||||||
void scc_frame_layout(scc_frame_layout_t *ctx, scc_mir_module_t *module) {
|
void scc_frame_layout(scc_frame_layout_t *ctx, scc_mir_module_t *module) {
|
||||||
Assert(ctx && ctx->impl_fn && module);
|
Assert(ctx && ctx->impl_fn && module);
|
||||||
|
LOG_DEBUG(" frame layout for %zu funcs",
|
||||||
|
scc_vec_size(module->cfg_module.funcs));
|
||||||
scc_vec_foreach(module->cfg_module.funcs, i) {
|
scc_vec_foreach(module->cfg_module.funcs, i) {
|
||||||
if (i == 0)
|
if (i == 0)
|
||||||
continue;
|
continue;
|
||||||
scc_mir_func_t *func = &scc_vec_at(module->cfg_module.funcs, i);
|
scc_mir_func_t *func = &scc_vec_at(module->cfg_module.funcs, i);
|
||||||
ctx->offset = SCC_MIR_FUNC_META(func)->frame_size;
|
ctx->offset = SCC_MIR_FUNC_META(func)->frame_size;
|
||||||
|
LOG_TRACE(" func[%zu] frame_size=%zu", (size_t)i,
|
||||||
|
(size_t)ctx->offset);
|
||||||
ctx->impl_fn(ctx, module, func);
|
ctx->impl_fn(ctx, module, func);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void scc_prolog_epilog(scc_prolog_epilog_t *ctx, scc_mir_module_t *module) {
|
void scc_prolog_epilog(scc_prolog_epilog_t *ctx, scc_mir_module_t *module) {
|
||||||
Assert(ctx && ctx->epilog && ctx->prolog && module);
|
Assert(ctx && ctx->epilog && ctx->prolog && module);
|
||||||
|
LOG_DEBUG(" prolog/epilog for %zu funcs",
|
||||||
|
scc_vec_size(module->cfg_module.funcs));
|
||||||
scc_vec_foreach(module->cfg_module.funcs, i) {
|
scc_vec_foreach(module->cfg_module.funcs, i) {
|
||||||
if (i == 0)
|
if (i == 0)
|
||||||
continue;
|
continue;
|
||||||
@@ -58,29 +66,38 @@ void scc_prolog_epilog(scc_prolog_epilog_t *ctx, scc_mir_module_t *module) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
void scc_mir_pass(scc_mir_module_t *mir_module, scc_mir_pass_stage_t stage) {
|
void scc_mir_pass(scc_mir_module_t *mir_module, scc_mir_pass_stage_t stage) {
|
||||||
|
LOG_INFO("running MIR passes (stage=%d, %zu funcs)", (int)stage,
|
||||||
|
scc_vec_size(mir_module->cfg_module.funcs));
|
||||||
|
|
||||||
|
LOG_DEBUG(" pass 1/3: register allocation");
|
||||||
scc_reg_alloc_ctx_t reg_alloc_ctx = {.func = nullptr, .ops = {0}};
|
scc_reg_alloc_ctx_t reg_alloc_ctx = {.func = nullptr, .ops = {0}};
|
||||||
scc_reg_alloc_fill_arch_x86(®_alloc_ctx.ops);
|
scc_reg_alloc_fill_arch_x86(®_alloc_ctx.ops);
|
||||||
scc_win_pc_x64_reg_alloc_fill(®_alloc_ctx.ops);
|
scc_win_pc_x64_reg_alloc_fill(®_alloc_ctx.ops);
|
||||||
|
|
||||||
scc_reg_alloc(®_alloc_ctx, mir_module);
|
scc_reg_alloc(®_alloc_ctx, mir_module);
|
||||||
if (stage == SCC_MIR_STAGE_REGALLOC) {
|
if (stage == SCC_MIR_STAGE_REGALLOC) {
|
||||||
|
LOG_DEBUG(" stop after regalloc");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
void scc_x86_peephole_optimize(scc_mir_module_t * module);
|
void scc_x86_peephole_optimize(scc_mir_module_t * module);
|
||||||
// scc_x86_peephole_optimize(mir_module);
|
// scc_x86_peephole_optimize(mir_module);
|
||||||
|
|
||||||
|
LOG_DEBUG(" pass 2/3: frame layout");
|
||||||
scc_frame_layout_t frame_layout_ctx = {0};
|
scc_frame_layout_t frame_layout_ctx = {0};
|
||||||
scc_win_pc_x64_frame_layout_init(&frame_layout_ctx);
|
scc_win_pc_x64_frame_layout_init(&frame_layout_ctx);
|
||||||
scc_frame_layout(&frame_layout_ctx, mir_module);
|
scc_frame_layout(&frame_layout_ctx, mir_module);
|
||||||
if (stage == SCC_MIR_STAGE_FRAME_LAYOUT) {
|
if (stage == SCC_MIR_STAGE_FRAME_LAYOUT) {
|
||||||
|
LOG_DEBUG(" stop after frame layout");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
LOG_DEBUG(" pass 3/3: prolog/epilog");
|
||||||
scc_prolog_epilog_t prolog_epilog_ctx = {0};
|
scc_prolog_epilog_t prolog_epilog_ctx = {0};
|
||||||
scc_win_pc_x64_prolog_epilog_init(&prolog_epilog_ctx);
|
scc_win_pc_x64_prolog_epilog_init(&prolog_epilog_ctx);
|
||||||
scc_prolog_epilog(&prolog_epilog_ctx, mir_module);
|
scc_prolog_epilog(&prolog_epilog_ctx, mir_module);
|
||||||
if (stage == SCC_MIR_STAGE_PROLOGUE_EPILOGUE) {
|
if (stage == SCC_MIR_STAGE_PROLOGUE_EPILOGUE) {
|
||||||
|
LOG_DEBUG(" stop after prolog/epilog");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
26
libs/ir2mcode/include/scc_ir2mcode_log.h
Normal file
26
libs/ir2mcode/include/scc_ir2mcode_log.h
Normal file
@@ -0,0 +1,26 @@
|
|||||||
|
#ifndef __SCC_IR2MCODE_LOG_H__
|
||||||
|
#define __SCC_IR2MCODE_LOG_H__
|
||||||
|
|
||||||
|
typedef struct logger logger_t;
|
||||||
|
extern logger_t __scc_ir2mcode_log;
|
||||||
|
extern logger_t __scc_ir2mcode_user;
|
||||||
|
|
||||||
|
#define SCC_LOG_HANDLER &__scc_ir2mcode_user
|
||||||
|
#define LOG_DEFAULT_HANDLER &__scc_ir2mcode_log
|
||||||
|
#include <scc_log.h>
|
||||||
|
|
||||||
|
#ifdef __SCC_IR2MCODE_LOG_IMPL__
|
||||||
|
logger_t __scc_ir2mcode_log = {
|
||||||
|
.name = "ir2mcode",
|
||||||
|
.level = LOG_LEVEL_ALL,
|
||||||
|
.handler = log_default_handler,
|
||||||
|
};
|
||||||
|
|
||||||
|
logger_t __scc_ir2mcode_user = {
|
||||||
|
.name = "ir2mcode",
|
||||||
|
.level = LOG_LEVEL_ALL,
|
||||||
|
.user_handler = scc_log_handler,
|
||||||
|
};
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#endif
|
||||||
@@ -1,3 +1,6 @@
|
|||||||
|
#define __SCC_IR2MCODE_LOG_IMPL__
|
||||||
|
#include <scc_ir2mcode_log.h>
|
||||||
|
|
||||||
#include <scc_ir2mcode.h>
|
#include <scc_ir2mcode.h>
|
||||||
#include <scc_mcode.h>
|
#include <scc_mcode.h>
|
||||||
#include <scc_mir_module.h>
|
#include <scc_mir_module.h>
|
||||||
@@ -117,10 +120,13 @@ void scc_ir2mcode_patch(scc_mcode_t *mcode, scc_reloc_t *reloc, i64 value) {
|
|||||||
void scc_ir2mcode(scc_mcode_t *mcode, scc_reloc_vec_t *relocs,
|
void scc_ir2mcode(scc_mcode_t *mcode, scc_reloc_vec_t *relocs,
|
||||||
const scc_mir_module_t *mir_module) {
|
const scc_mir_module_t *mir_module) {
|
||||||
Assert(mir_module != nullptr && mcode != nullptr);
|
Assert(mir_module != nullptr && mcode != nullptr);
|
||||||
|
LOG_INFO("MIR -> machine code (%zu funcs)",
|
||||||
|
scc_vec_size(mir_module->cfg_module.funcs));
|
||||||
scc_vec_foreach(mir_module->cfg_module.funcs, i) {
|
scc_vec_foreach(mir_module->cfg_module.funcs, i) {
|
||||||
if (i == 0)
|
if (i == 0)
|
||||||
continue;
|
continue;
|
||||||
scc_mir_func_t *func = &scc_vec_at(mir_module->cfg_module.funcs, i);
|
scc_mir_func_t *func = &scc_vec_at(mir_module->cfg_module.funcs, i);
|
||||||
|
LOG_DEBUG(" func[%zu]: %s", (size_t)i, func->name ? func->name : "?");
|
||||||
scc_vec_foreach(func->bblocks, i) {
|
scc_vec_foreach(func->bblocks, i) {
|
||||||
scc_cfg_bblock_id_t id = scc_vec_at(func->bblocks, i);
|
scc_cfg_bblock_id_t id = scc_vec_at(func->bblocks, i);
|
||||||
const scc_cfg_bblock_t *bb =
|
const scc_cfg_bblock_t *bb =
|
||||||
|
|||||||
@@ -1,3 +1,5 @@
|
|||||||
|
#include <scc_ir2mcode_log.h>
|
||||||
|
|
||||||
#include <scc_ir2sccf.h>
|
#include <scc_ir2sccf.h>
|
||||||
|
|
||||||
static inline void scc_ir_sym_to_sccf_sym(const scc_cfg_symbol_t *symbol,
|
static inline void scc_ir_sym_to_sccf_sym(const scc_cfg_symbol_t *symbol,
|
||||||
@@ -47,6 +49,8 @@ static inline void scc_ir_symbol_to_sect_data(const scc_cfg_symbol_t *symbol,
|
|||||||
|
|
||||||
static void emit_mir_module(sccf_builder_t *builder, scc_mcode_t *mcode,
|
static void emit_mir_module(sccf_builder_t *builder, scc_mcode_t *mcode,
|
||||||
scc_mir_module_t *mir_module) {
|
scc_mir_module_t *mir_module) {
|
||||||
|
LOG_DEBUG("emit MIR to SCCF (%zu funcs)",
|
||||||
|
scc_vec_size(mir_module->cfg_module.funcs));
|
||||||
|
|
||||||
scc_hashtable_t bblock_offset;
|
scc_hashtable_t bblock_offset;
|
||||||
|
|
||||||
@@ -54,6 +58,8 @@ static void emit_mir_module(sccf_builder_t *builder, scc_mcode_t *mcode,
|
|||||||
if (i == 0)
|
if (i == 0)
|
||||||
continue;
|
continue;
|
||||||
scc_mir_func_t *func = &scc_vec_at(mir_module->cfg_module.funcs, i);
|
scc_mir_func_t *func = &scc_vec_at(mir_module->cfg_module.funcs, i);
|
||||||
|
LOG_DEBUG(" emit func[%zu] '%s'", (size_t)i,
|
||||||
|
func->name ? func->name : "?");
|
||||||
|
|
||||||
sccf_sym_t *sym = sccf_builder_get_symbol_unsafe(builder, func->name);
|
sccf_sym_t *sym = sccf_builder_get_symbol_unsafe(builder, func->name);
|
||||||
Assert(sym != nullptr);
|
Assert(sym != nullptr);
|
||||||
@@ -111,8 +117,9 @@ static void emit_mir_module(sccf_builder_t *builder, scc_mcode_t *mcode,
|
|||||||
}
|
}
|
||||||
|
|
||||||
void scc_ir2sccf(sccf_builder_t *builder, scc_mir_module_t *mir_module) {
|
void scc_ir2sccf(sccf_builder_t *builder, scc_mir_module_t *mir_module) {
|
||||||
// mir_module->symbol_metas
|
LOG_INFO("MIR -> SCCF conversion (%zu symbols, %zu funcs)",
|
||||||
// mir_module->cfg_module.funcs
|
scc_vec_size(mir_module->cfg_module.symbols),
|
||||||
|
scc_vec_size(mir_module->cfg_module.funcs));
|
||||||
sccf_builder_init(builder);
|
sccf_builder_init(builder);
|
||||||
sccf_sect_data_t sect_data;
|
sccf_sect_data_t sect_data;
|
||||||
scc_vec_init(sect_data);
|
scc_vec_init(sect_data);
|
||||||
|
|||||||
@@ -1,48 +0,0 @@
|
|||||||
#ifndef __SCC_LEXER_LOG_H__
|
|
||||||
#define __SCC_LEXER_LOG_H__
|
|
||||||
|
|
||||||
#include <scc_core.h>
|
|
||||||
|
|
||||||
#ifndef LEX_LOG_LEVEL
|
|
||||||
#define LEX_LOG_LEVEL 4
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#if LEX_LOG_LEVEL <= 1
|
|
||||||
#define LEX_NOTSET(fmt, ...) MLOG_NOTSET(&__scc_lexer_log, fmt, ##__VA_ARGS__)
|
|
||||||
#else
|
|
||||||
#define LEX_NOTSET(fmt, ...)
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#if LEX_LOG_LEVEL <= 2
|
|
||||||
#define LEX_DEBUG(fmt, ...) MLOG_DEBUG(&__scc_lexer_log, fmt, ##__VA_ARGS__)
|
|
||||||
#else
|
|
||||||
#define LEX_DEBUG(fmt, ...)
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#if LEX_LOG_LEVEL <= 3
|
|
||||||
#define LEX_INFO(fmt, ...) MLOG_INFO(&__scc_lexer_log, fmt, ##__VA_ARGS__)
|
|
||||||
#else
|
|
||||||
#define LEX_INFO(fmt, ...)
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#if LEX_LOG_LEVEL <= 4
|
|
||||||
#define LEX_WARN(fmt, ...) MLOG_WARN(&__scc_lexer_log, fmt, ##__VA_ARGS__)
|
|
||||||
#else
|
|
||||||
#define LEX_WARN(fmt, ...)
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#if LEX_LOG_LEVEL <= 5
|
|
||||||
#define LEX_ERROR(fmt, ...) MLOG_ERROR(&__scc_lexer_log, fmt, ##__VA_ARGS__)
|
|
||||||
#else
|
|
||||||
#define LEX_ERROR(fmt, ...)
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#if LEX_LOG_LEVEL <= 6
|
|
||||||
#define LEX_FATAL(fmt, ...) MLOG_FATAL(&__scc_lexer_log, fmt, ##__VA_ARGS__)
|
|
||||||
#else
|
|
||||||
#define LEX_FATAL(fmt, ...)
|
|
||||||
#endif
|
|
||||||
|
|
||||||
extern logger_t __scc_lexer_log;
|
|
||||||
|
|
||||||
#endif /* __SCC_LEXER_LOG_H__ */
|
|
||||||
26
libs/lexer/include/scc_lexer_log.h
Normal file
26
libs/lexer/include/scc_lexer_log.h
Normal file
@@ -0,0 +1,26 @@
|
|||||||
|
#ifndef __SCC_LEXER_LOG_H__
|
||||||
|
#define __SCC_LEXER_LOG_H__
|
||||||
|
|
||||||
|
typedef struct logger logger_t;
|
||||||
|
extern logger_t __scc_lexer_log;
|
||||||
|
extern logger_t __scc_lexer_user;
|
||||||
|
|
||||||
|
#define SCC_LOG_HANDLER &__scc_lexer_user
|
||||||
|
#define LOG_DEFAULT_HANDLER &__scc_lexer_log
|
||||||
|
#include <scc_log.h>
|
||||||
|
|
||||||
|
#ifdef __SCC_LEXER_LOG_IMPL__
|
||||||
|
logger_t __scc_lexer_log = {
|
||||||
|
.name = "lexer",
|
||||||
|
.level = LOG_LEVEL_ALL,
|
||||||
|
.handler = log_default_handler,
|
||||||
|
};
|
||||||
|
|
||||||
|
logger_t __scc_lexer_user = {
|
||||||
|
.name = "lexer",
|
||||||
|
.level = LOG_LEVEL_ALL,
|
||||||
|
.user_handler = scc_log_handler,
|
||||||
|
};
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#endif /* __SCC_LEXER_LOG_H__ */
|
||||||
@@ -1,4 +1,6 @@
|
|||||||
#include <lexer_log.h>
|
#define __SCC_LEXER_LOG_IMPL__
|
||||||
|
#include <scc_lexer_log.h>
|
||||||
|
|
||||||
#include <scc_lexer.h>
|
#include <scc_lexer.h>
|
||||||
|
|
||||||
static const struct {
|
static const struct {
|
||||||
@@ -153,7 +155,7 @@ void scc_lexer_get_token(scc_lexer_t *lexer, scc_lexer_tok_t *token) {
|
|||||||
while (1) {
|
while (1) {
|
||||||
if (!next_char(lexer, &lex, &cur)) {
|
if (!next_char(lexer, &lex, &cur)) {
|
||||||
// 文件结束,注释未闭合
|
// 文件结束,注释未闭合
|
||||||
LOG_ERROR("Unterminated block comment");
|
SCC_ERROR(start_loc, "unterminated block comment");
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
if (cur.character == '*' && peek_char(lexer, &next) &&
|
if (cur.character == '*' && peek_char(lexer, &next) &&
|
||||||
@@ -234,7 +236,7 @@ void scc_lexer_get_token(scc_lexer_t *lexer, scc_lexer_tok_t *token) {
|
|||||||
next_char(lexer, &lex, &cur); // 开头的 '
|
next_char(lexer, &lex, &cur); // 开头的 '
|
||||||
while (1) {
|
while (1) {
|
||||||
if (!peek_char(lexer, &cur)) {
|
if (!peek_char(lexer, &cur)) {
|
||||||
LOG_ERROR("Unterminated character literal");
|
SCC_ERROR(start_loc, "unterminated character literal");
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
if (cur.character == '\'') {
|
if (cur.character == '\'') {
|
||||||
@@ -257,7 +259,7 @@ void scc_lexer_get_token(scc_lexer_t *lexer, scc_lexer_tok_t *token) {
|
|||||||
next_char(lexer, &lex, &cur); // 开头的 "
|
next_char(lexer, &lex, &cur); // 开头的 "
|
||||||
while (1) {
|
while (1) {
|
||||||
if (!peek_char(lexer, &cur)) {
|
if (!peek_char(lexer, &cur)) {
|
||||||
LOG_ERROR("Unterminated string literal");
|
SCC_ERROR(start_loc, "unterminated string literal");
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
if (cur.character == '"') {
|
if (cur.character == '"') {
|
||||||
@@ -487,7 +489,7 @@ void scc_lexer_get_token(scc_lexer_t *lexer, scc_lexer_tok_t *token) {
|
|||||||
token->type = token->type; // 上面已设
|
token->type = token->type; // 上面已设
|
||||||
token->loc = start_loc;
|
token->loc = start_loc;
|
||||||
token->lexeme = lex; // 转移所有权
|
token->lexeme = lex; // 转移所有权
|
||||||
LEX_DEBUG("get token `%s` (%s) at %s:%d:%d", scc_get_tok_name(token->type),
|
LOG_DEBUG("get token `%s` (%s) at %s:%d:%d", scc_get_tok_name(token->type),
|
||||||
scc_str_as_cstr(&token->lexeme), token->loc.name, token->loc.line,
|
scc_str_as_cstr(&token->lexeme), token->loc.name, token->loc.line,
|
||||||
token->loc.col);
|
token->loc.col);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,7 +0,0 @@
|
|||||||
#include <lexer_log.h>
|
|
||||||
|
|
||||||
logger_t __scc_lexer_log = {
|
|
||||||
.name = "lexer",
|
|
||||||
.level = LOG_LEVEL_ALL,
|
|
||||||
.handler = log_default_handler,
|
|
||||||
};
|
|
||||||
@@ -1,3 +1,4 @@
|
|||||||
|
#define LEX_LOG_LEVEL 1
|
||||||
#include <lexer_log.h>
|
#include <lexer_log.h>
|
||||||
#include <scc_lexer.h>
|
#include <scc_lexer.h>
|
||||||
#include <stdbool.h>
|
#include <stdbool.h>
|
||||||
@@ -24,12 +25,11 @@ int g_num_arr[3];
|
|||||||
int main(int argc, char *argv[]) {
|
int main(int argc, char *argv[]) {
|
||||||
// int num = 0;
|
// int num = 0;
|
||||||
if (argc == 3 && strcmp(argv[2], "--debug") == 0) {
|
if (argc == 3 && strcmp(argv[2], "--debug") == 0) {
|
||||||
log_set_level(nullptr, LOG_LEVEL_ALL);
|
log_set_level(&__scc_lexer_log, LOG_LEVEL_ALL);
|
||||||
} else {
|
} else {
|
||||||
// FIXME it is a hack lexer_logger
|
log_set_level(&__scc_lexer_log,
|
||||||
log_set_level(&__scc_lexer_log, LOG_LEVEL_NOTSET);
|
LOG_LEVEL_INFO | LOG_LEVEL_WARN | LOG_LEVEL_ERROR |
|
||||||
log_set_level(nullptr, LOG_LEVEL_INFO | LOG_LEVEL_WARN |
|
LOG_LEVEL_FATAL);
|
||||||
LOG_LEVEL_ERROR | LOG_LEVEL_FATAL);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
const char *file_name = __FILE__;
|
const char *file_name = __FILE__;
|
||||||
@@ -57,7 +57,7 @@ int main(int argc, char *argv[]) {
|
|||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
LOG_INFO("get token [%-8s] `%s` at %s:%d:%d",
|
LEX_INFO("get token [%-8s] `%s` at %s:%d:%d",
|
||||||
scc_get_tok_name(token.type), scc_str_as_cstr(&token.lexeme),
|
scc_get_tok_name(token.type), scc_str_as_cstr(&token.lexeme),
|
||||||
token.loc.name, token.loc.line, token.loc.col);
|
token.loc.name, token.loc.line, token.loc.col);
|
||||||
scc_str_drop(&token.lexeme);
|
scc_str_drop(&token.lexeme);
|
||||||
@@ -65,6 +65,6 @@ int main(int argc, char *argv[]) {
|
|||||||
scc_sstream_drop_ring(ref);
|
scc_sstream_drop_ring(ref);
|
||||||
scc_sstream_drop(&stream);
|
scc_sstream_drop(&stream);
|
||||||
|
|
||||||
LOG_INFO("Lexer is Ok...");
|
LEX_INFO("Lexer is Ok...");
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -50,7 +50,7 @@ static inline void scc_mcode_adopt_buf(scc_mcode_t *mcode,
|
|||||||
mcode->code.data = buf->data;
|
mcode->code.data = buf->data;
|
||||||
buf->size = 0;
|
buf->size = 0;
|
||||||
buf->cap = 0;
|
buf->cap = 0;
|
||||||
buf->data = NULL;
|
buf->data = nullptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -68,7 +68,7 @@ static inline void scc_mcode_disown_buf(scc_mcode_t *mcode,
|
|||||||
out->data = mcode->code.data;
|
out->data = mcode->code.data;
|
||||||
mcode->code.size = 0;
|
mcode->code.size = 0;
|
||||||
mcode->code.cap = 0;
|
mcode->code.cap = 0;
|
||||||
mcode->code.data = NULL;
|
mcode->code.data = nullptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
static inline void scc_mcode_add_u8(scc_mcode_t *mcode, u8 data) {
|
static inline void scc_mcode_add_u8(scc_mcode_t *mcode, u8 data) {
|
||||||
|
|||||||
26
libs/mcode/include/scc_mcode_log.h
Normal file
26
libs/mcode/include/scc_mcode_log.h
Normal file
@@ -0,0 +1,26 @@
|
|||||||
|
#ifndef __SCC_MCODE_LOG_H__
|
||||||
|
#define __SCC_MCODE_LOG_H__
|
||||||
|
|
||||||
|
typedef struct logger logger_t;
|
||||||
|
extern logger_t __scc_mcode_log;
|
||||||
|
extern logger_t __scc_mcode_user;
|
||||||
|
|
||||||
|
#define SCC_LOG_HANDLER &__scc_mcode_user
|
||||||
|
#define LOG_DEFAULT_HANDLER &__scc_mcode_log
|
||||||
|
#include <scc_log.h>
|
||||||
|
|
||||||
|
#ifdef __SCC_MCODE_LOG_IMPL__
|
||||||
|
logger_t __scc_mcode_log = {
|
||||||
|
.name = "mcode",
|
||||||
|
.level = LOG_LEVEL_ALL,
|
||||||
|
.handler = log_default_handler,
|
||||||
|
};
|
||||||
|
|
||||||
|
logger_t __scc_mcode_user = {
|
||||||
|
.name = "mcode",
|
||||||
|
.level = LOG_LEVEL_ALL,
|
||||||
|
.user_handler = scc_log_handler,
|
||||||
|
};
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#endif
|
||||||
2
libs/mcode/src/scc_mcode.c
Normal file
2
libs/mcode/src/scc_mcode.c
Normal file
@@ -0,0 +1,2 @@
|
|||||||
|
#define __SCC_MCODE_LOG_IMPL__
|
||||||
|
#include <scc_mcode_log.h>
|
||||||
@@ -1,14 +1,9 @@
|
|||||||
|
#include <scc_mcode_log.h>
|
||||||
|
|
||||||
#include <x86/scc_x86_encode.h>
|
#include <x86/scc_x86_encode.h>
|
||||||
#include <x86/scc_x86_iform.h>
|
#include <x86/scc_x86_iform.h>
|
||||||
#include <x86/scc_x86_reg.h>
|
#include <x86/scc_x86_reg.h>
|
||||||
|
|
||||||
#if 1
|
|
||||||
#ifdef LOG_INFO
|
|
||||||
#undef LOG_INFO
|
|
||||||
#endif
|
|
||||||
#define LOG_INFO(...)
|
|
||||||
#endif
|
|
||||||
|
|
||||||
/* ---------- 内部辅助 ---------- */
|
/* ---------- 内部辅助 ---------- */
|
||||||
static inline void emit_u8(scc_mcode_t *m, uint8_t v) {
|
static inline void emit_u8(scc_mcode_t *m, uint8_t v) {
|
||||||
scc_mcode_add_u8(m, v);
|
scc_mcode_add_u8(m, v);
|
||||||
@@ -167,7 +162,7 @@ static void emit_rex(scc_mcode_t *m, const scc_x86_encoding_t *enc,
|
|||||||
if (b != SCC_X86_REG_INVALID && reg_rex_bit(b))
|
if (b != SCC_X86_REG_INVALID && reg_rex_bit(b))
|
||||||
rex |= 1;
|
rex |= 1;
|
||||||
if (rex != 0x40) {
|
if (rex != 0x40) {
|
||||||
LOG_INFO("[REX] emit 0x%02x", (uint8_t)rex);
|
LOG_TRACE("[REX] emit 0x%02x", (uint8_t)rex);
|
||||||
emit_u8(m, (uint8_t)rex);
|
emit_u8(m, (uint8_t)rex);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -249,7 +244,7 @@ static void emit_immediate(scc_mcode_t *m, const scc_x86_encoding_t *enc,
|
|||||||
else if (!scc_strcmp(oc2, "q"))
|
else if (!scc_strcmp(oc2, "q"))
|
||||||
imm_size = 8;
|
imm_size = 8;
|
||||||
|
|
||||||
LOG_INFO("[IMM] val=%lld size=%d", imm_val, imm_size);
|
LOG_TRACE("[IMM] val=%lld size=%d", imm_val, imm_size);
|
||||||
switch (imm_size) {
|
switch (imm_size) {
|
||||||
case 1:
|
case 1:
|
||||||
emit_u8(m, (uint8_t)imm_val);
|
emit_u8(m, (uint8_t)imm_val);
|
||||||
@@ -287,7 +282,7 @@ static void emit_modrm_sib_disp(scc_mcode_t *m,
|
|||||||
for (int i = 0; i < num_ops; i++) {
|
for (int i = 0; i < num_ops; i++) {
|
||||||
const char *tname = tmpl[i].name;
|
const char *tname = tmpl[i].name;
|
||||||
if (ops[i].kind == SCC_X86_OPR_REG) {
|
if (ops[i].kind == SCC_X86_OPR_REG) {
|
||||||
LOG_INFO("[OPD] %d: REG kind, name=\"%s\" reg=%d", i, tname,
|
LOG_TRACE("[OPD] %d: REG kind, name=\"%s\" reg=%d", i, tname,
|
||||||
ops[i].reg);
|
ops[i].reg);
|
||||||
if (scc_strcmp(tname, "REG0") == 0)
|
if (scc_strcmp(tname, "REG0") == 0)
|
||||||
reg_r = ops[i].reg;
|
reg_r = ops[i].reg;
|
||||||
@@ -307,7 +302,7 @@ static void emit_modrm_sib_disp(scc_mcode_t *m,
|
|||||||
imm_idx = i;
|
imm_idx = i;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
LOG_INFO("[MODRM] reg_r=%d (ord=%d) reg_b=%d (ord=%d)", reg_r,
|
LOG_TRACE("[MODRM] reg_r=%d (ord=%d) reg_b=%d (ord=%d)", reg_r,
|
||||||
scc_reg_ordinal(reg_r), reg_b, scc_reg_ordinal(reg_b));
|
scc_reg_ordinal(reg_r), reg_b, scc_reg_ordinal(reg_b));
|
||||||
|
|
||||||
uint8_t modrm = 0;
|
uint8_t modrm = 0;
|
||||||
@@ -426,7 +421,7 @@ static void emit_modrm_sib_disp(scc_mcode_t *m,
|
|||||||
reg_b == SCC_X86_REG_INVALID) {
|
reg_b == SCC_X86_REG_INVALID) {
|
||||||
modrm = 0xC0 | (reg_low3(reg_r) & 7);
|
modrm = 0xC0 | (reg_low3(reg_r) & 7);
|
||||||
emit_u8(m, modrm);
|
emit_u8(m, modrm);
|
||||||
LOG_INFO("[MODRM] single reg operand treated as rm, emit 0x%02x",
|
LOG_TRACE("[MODRM] single reg operand treated as rm, emit 0x%02x",
|
||||||
modrm);
|
modrm);
|
||||||
} else {
|
} else {
|
||||||
modrm = 0xC0;
|
modrm = 0xC0;
|
||||||
@@ -449,7 +444,7 @@ static void emit_modrm_sib_disp(scc_mcode_t *m,
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
LOG_INFO("[MODRM] emit byte 0x%02x", modrm);
|
LOG_TRACE("[MODRM] emit byte 0x%02x", modrm);
|
||||||
|
|
||||||
// 立即数在 ModRM 后发射
|
// 立即数在 ModRM 后发射
|
||||||
if (imm_idx >= 0) {
|
if (imm_idx >= 0) {
|
||||||
@@ -469,7 +464,7 @@ int scc_x86_encode_inst(scc_mcode_t *mcode, scc_x86_iform_t iform,
|
|||||||
int num_ops = info->num_explicit_ops;
|
int num_ops = info->num_explicit_ops;
|
||||||
const scc_x86_encoding_t *enc = &info->encode;
|
const scc_x86_encoding_t *enc = &info->encode;
|
||||||
const scc_x86_operand_t *tmpl = info->ops;
|
const scc_x86_operand_t *tmpl = info->ops;
|
||||||
LOG_INFO("[ENCODE] %s", info->iform_name);
|
LOG_TRACE("[ENCODE] %s", info->iform_name);
|
||||||
|
|
||||||
scc_x86_reg_t reg_field = SCC_X86_REG_INVALID;
|
scc_x86_reg_t reg_field = SCC_X86_REG_INVALID;
|
||||||
scc_x86_reg_t rm_field = SCC_X86_REG_INVALID;
|
scc_x86_reg_t rm_field = SCC_X86_REG_INVALID;
|
||||||
@@ -521,7 +516,7 @@ int scc_x86_encode_inst(scc_mcode_t *mcode, scc_x86_iform_t iform,
|
|||||||
}
|
}
|
||||||
|
|
||||||
int op_width = infer_operand_width(info, ops);
|
int op_width = infer_operand_width(info, ops);
|
||||||
LOG_INFO("[OPWIDTH] %d bits", op_width);
|
LOG_TRACE("[OPWIDTH] %d bits", op_width);
|
||||||
|
|
||||||
if (!enc->has_modrm) {
|
if (!enc->has_modrm) {
|
||||||
rm_field = reg_field;
|
rm_field = reg_field;
|
||||||
|
|||||||
@@ -71,7 +71,6 @@ static inline void scc_parser_reset(scc_parser_t *parser) {
|
|||||||
scc_ring_reset(*parser->ring);
|
scc_ring_reset(*parser->ring);
|
||||||
}
|
}
|
||||||
|
|
||||||
#include <scc_pos_log.h>
|
|
||||||
static inline scc_pos_t scc_parser_got_current_pos(scc_parser_t *parser) {
|
static inline scc_pos_t scc_parser_got_current_pos(scc_parser_t *parser) {
|
||||||
const scc_lexer_tok_t *tok = scc_parser_peek(parser);
|
const scc_lexer_tok_t *tok = scc_parser_peek(parser);
|
||||||
scc_pos_t pos = scc_pos_create();
|
scc_pos_t pos = scc_pos_create();
|
||||||
|
|||||||
26
libs/parser/include/scc_parser_log.h
Normal file
26
libs/parser/include/scc_parser_log.h
Normal file
@@ -0,0 +1,26 @@
|
|||||||
|
#ifndef __SCC_PARSER_LOG_H__
|
||||||
|
#define __SCC_PARSER_LOG_H__
|
||||||
|
|
||||||
|
typedef struct logger logger_t;
|
||||||
|
extern logger_t __scc_parser_log;
|
||||||
|
extern logger_t __scc_parser_user;
|
||||||
|
|
||||||
|
#define SCC_LOG_HANDLER &__scc_parser_user
|
||||||
|
#define LOG_DEFAULT_HANDLER &__scc_parser_log
|
||||||
|
#include <scc_log.h>
|
||||||
|
|
||||||
|
#ifdef __SCC_PARSER_LOG_IMPL__
|
||||||
|
logger_t __scc_parser_log = {
|
||||||
|
.name = "parser",
|
||||||
|
.level = LOG_LEVEL_ALL,
|
||||||
|
.handler = log_default_handler,
|
||||||
|
};
|
||||||
|
|
||||||
|
logger_t __scc_parser_user = {
|
||||||
|
.name = "parser",
|
||||||
|
.level = LOG_LEVEL_ALL,
|
||||||
|
.user_handler = scc_log_handler,
|
||||||
|
};
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#endif
|
||||||
@@ -150,6 +150,7 @@ A.2.4 External definitions
|
|||||||
declaration
|
declaration
|
||||||
declaration-list declaration
|
declaration-list declaration
|
||||||
*/
|
*/
|
||||||
|
#include <scc_parser_log.h>
|
||||||
|
|
||||||
#include <parser_utils.h>
|
#include <parser_utils.h>
|
||||||
#include <scc_ast_utils.h>
|
#include <scc_ast_utils.h>
|
||||||
@@ -157,6 +158,7 @@ A.2.4 External definitions
|
|||||||
|
|
||||||
scc_ast_expr_t *scc_parse_initializer(scc_parser_t *parser,
|
scc_ast_expr_t *scc_parse_initializer(scc_parser_t *parser,
|
||||||
scc_ast_expr_t *base) {
|
scc_ast_expr_t *base) {
|
||||||
|
LOG_DEBUG("scc_parse_initializer()");
|
||||||
/*
|
/*
|
||||||
initializer:
|
initializer:
|
||||||
assignment-expression
|
assignment-expression
|
||||||
@@ -179,10 +181,11 @@ scc_ast_expr_t *scc_parse_initializer(scc_parser_t *parser,
|
|||||||
tok_ptr = scc_parser_peek(parser);
|
tok_ptr = scc_parser_peek(parser);
|
||||||
scc_ast_expr_t *init = nullptr;
|
scc_ast_expr_t *init = nullptr;
|
||||||
if (!(tok_ptr && tok_ptr->type == SCC_TOK_L_BRACE)) {
|
if (!(tok_ptr && tok_ptr->type == SCC_TOK_L_BRACE)) {
|
||||||
// TODO int a = 1, b = 1;
|
LOG_TRACE(" simple initializer (assignment-expr)");
|
||||||
init = scc_parse_assignment_expression(parser);
|
init = scc_parse_assignment_expression(parser);
|
||||||
return init;
|
return init;
|
||||||
}
|
}
|
||||||
|
LOG_TRACE(" compound initializer {...}");
|
||||||
scc_parser_next_consume(parser, &tok);
|
scc_parser_next_consume(parser, &tok);
|
||||||
scc_pos_t pos = tok.loc;
|
scc_pos_t pos = tok.loc;
|
||||||
scc_lexer_tok_drop(&tok);
|
scc_lexer_tok_drop(&tok);
|
||||||
@@ -205,7 +208,10 @@ scc_ast_expr_t *scc_parse_initializer(scc_parser_t *parser,
|
|||||||
scc_parser_next_consume(parser, &tok);
|
scc_parser_next_consume(parser, &tok);
|
||||||
lhs = SCC_AST_ALLOC_EXPR(parser->ast_module);
|
lhs = SCC_AST_ALLOC_EXPR(parser->ast_module);
|
||||||
Assert(lhs != nullptr);
|
Assert(lhs != nullptr);
|
||||||
scc_ast_expr_member_init(lhs, ptr, scc_ast_module_intern(parser->ast_module, 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;
|
||||||
@@ -261,6 +267,7 @@ scc_ast_expr_t *scc_parse_initializer(scc_parser_t *parser,
|
|||||||
}
|
}
|
||||||
|
|
||||||
scc_ast_decl_t *scc_parse_declaration(scc_parser_t *parser) {
|
scc_ast_decl_t *scc_parse_declaration(scc_parser_t *parser) {
|
||||||
|
LOG_DEBUG("scc_parse_declaration()");
|
||||||
const scc_lexer_tok_t *tok_ptr = nullptr;
|
const scc_lexer_tok_t *tok_ptr = nullptr;
|
||||||
|
|
||||||
scc_ast_decl_t *decl_list = nullptr;
|
scc_ast_decl_t *decl_list = nullptr;
|
||||||
@@ -283,12 +290,14 @@ CONTINUE:
|
|||||||
}
|
}
|
||||||
tok_ptr = scc_parser_peek(parser);
|
tok_ptr = scc_parser_peek(parser);
|
||||||
if (tok_ptr->type == SCC_TOK_ASSIGN) {
|
if (tok_ptr->type == SCC_TOK_ASSIGN) {
|
||||||
|
LOG_TRACE(" declaration with initializer");
|
||||||
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_module);
|
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) {
|
||||||
|
LOG_DEBUG(" function definition '%s'", decl->name ? decl->name : "?");
|
||||||
scc_parse_decl_sema(parser, decl);
|
scc_parse_decl_sema(parser, decl);
|
||||||
|
|
||||||
// 进入函数作用域(用于参数和标签)
|
// 进入函数作用域(用于参数和标签)
|
||||||
@@ -317,6 +326,7 @@ CONTINUE:
|
|||||||
|
|
||||||
tok_ptr = scc_parser_peek(parser);
|
tok_ptr = scc_parser_peek(parser);
|
||||||
if (tok_ptr->type == SCC_TOK_SEMICOLON) {
|
if (tok_ptr->type == SCC_TOK_SEMICOLON) {
|
||||||
|
LOG_TRACE(" declaration ends with ';'");
|
||||||
scc_parser_next_consume(parser, nullptr);
|
scc_parser_next_consume(parser, nullptr);
|
||||||
if (decl_list)
|
if (decl_list)
|
||||||
scc_vec_push(decl_list_vec, decl);
|
scc_vec_push(decl_list_vec, decl);
|
||||||
|
|||||||
@@ -104,6 +104,7 @@ A.2.1 Expressions
|
|||||||
constant-expression:
|
constant-expression:
|
||||||
conditional-expression
|
conditional-expression
|
||||||
*/
|
*/
|
||||||
|
#include <scc_parser_log.h>
|
||||||
|
|
||||||
#include <parser_utils.h>
|
#include <parser_utils.h>
|
||||||
#include <scc_ast_utils.h>
|
#include <scc_ast_utils.h>
|
||||||
@@ -342,6 +343,7 @@ static void parser_sync(scc_parser_t *parser) {
|
|||||||
|
|
||||||
static scc_ast_expr_t *parse_expression_with_precedence(scc_parser_t *parser,
|
static scc_ast_expr_t *parse_expression_with_precedence(scc_parser_t *parser,
|
||||||
int min_prec) {
|
int min_prec) {
|
||||||
|
LOG_TRACE("parse_expression_with_precedence(min_prec=%d)", min_prec);
|
||||||
// 从最底层(cast-expression)开始
|
// 从最底层(cast-expression)开始
|
||||||
scc_ast_expr_t *left = parse_cast_expression(parser);
|
scc_ast_expr_t *left = parse_cast_expression(parser);
|
||||||
if (!left)
|
if (!left)
|
||||||
@@ -361,6 +363,7 @@ static scc_ast_expr_t *parse_expression_with_precedence(scc_parser_t *parser,
|
|||||||
if (!scc_parser_next_consume(parser, &op_tok))
|
if (!scc_parser_next_consume(parser, &op_tok))
|
||||||
break;
|
break;
|
||||||
scc_ast_expr_op_t op = map_token_to_binary_op(op_tok.type);
|
scc_ast_expr_op_t op = map_token_to_binary_op(op_tok.type);
|
||||||
|
LOG_TRACE(" binary op=%d at prec=%d", op, prec);
|
||||||
scc_lexer_tok_drop(&op_tok);
|
scc_lexer_tok_drop(&op_tok);
|
||||||
|
|
||||||
// 解析右操作数(优先级 +1,确保左结合)
|
// 解析右操作数(优先级 +1,确保左结合)
|
||||||
@@ -377,10 +380,12 @@ static scc_ast_expr_t *parse_expression_with_precedence(scc_parser_t *parser,
|
|||||||
scc_ast_expr_binary_init(expr, op, left, right, left->base.loc);
|
scc_ast_expr_binary_init(expr, op, left, right, left->base.loc);
|
||||||
left = expr;
|
left = expr;
|
||||||
}
|
}
|
||||||
|
LOG_TRACE(" => expr type=%d", left ? left->base.type : -1);
|
||||||
return left;
|
return left;
|
||||||
}
|
}
|
||||||
// 赋值表达式(右结合)
|
// 赋值表达式(右结合)
|
||||||
scc_ast_expr_t *scc_parse_assignment_expression(scc_parser_t *parser) {
|
scc_ast_expr_t *scc_parse_assignment_expression(scc_parser_t *parser) {
|
||||||
|
LOG_TRACE("scc_parse_assignment_expression()");
|
||||||
// 先解析左侧的 unary-expression(C 标准规定赋值左边必须是
|
// 先解析左侧的 unary-expression(C 标准规定赋值左边必须是
|
||||||
// unary-expression)
|
// unary-expression)
|
||||||
scc_ast_expr_t *left = nullptr;
|
scc_ast_expr_t *left = nullptr;
|
||||||
@@ -400,6 +405,7 @@ scc_ast_expr_t *scc_parse_assignment_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_assign_op(op_tok.type);
|
scc_ast_expr_op_t op = map_token_to_assign_op(op_tok.type);
|
||||||
|
LOG_TRACE(" assignment op=%d", op);
|
||||||
scc_lexer_tok_drop(&op_tok);
|
scc_lexer_tok_drop(&op_tok);
|
||||||
|
|
||||||
// 解析右侧(右结合:继续调用 parse_assignment_expression)
|
// 解析右侧(右结合:继续调用 parse_assignment_expression)
|
||||||
@@ -420,6 +426,7 @@ scc_ast_expr_t *scc_parse_assignment_expression(scc_parser_t *parser) {
|
|||||||
|
|
||||||
// 条件表达式(右结合)
|
// 条件表达式(右结合)
|
||||||
static scc_ast_expr_t *parse_conditional_expression(scc_parser_t *parser) {
|
static scc_ast_expr_t *parse_conditional_expression(scc_parser_t *parser) {
|
||||||
|
LOG_TRACE("parse_conditional_expression()");
|
||||||
scc_ast_expr_t *cond_expr =
|
scc_ast_expr_t *cond_expr =
|
||||||
parse_expression_with_precedence(parser, PREC_LOGICAL_OR);
|
parse_expression_with_precedence(parser, PREC_LOGICAL_OR);
|
||||||
if (!cond_expr)
|
if (!cond_expr)
|
||||||
@@ -466,6 +473,7 @@ static scc_ast_expr_t *parse_conditional_expression(scc_parser_t *parser) {
|
|||||||
|
|
||||||
// 类型转换表达式 (type-name) cast-expression
|
// 类型转换表达式 (type-name) cast-expression
|
||||||
static scc_ast_expr_t *parse_cast_expression(scc_parser_t *parser) {
|
static scc_ast_expr_t *parse_cast_expression(scc_parser_t *parser) {
|
||||||
|
LOG_TRACE("parse_cast_expression()");
|
||||||
const scc_lexer_tok_t *tok_ptr = scc_parser_peek(parser);
|
const scc_lexer_tok_t *tok_ptr = scc_parser_peek(parser);
|
||||||
scc_ast_qual_type_t *type = nullptr;
|
scc_ast_qual_type_t *type = nullptr;
|
||||||
if (tok_ptr && tok_ptr->type == SCC_TOK_L_PAREN) {
|
if (tok_ptr && tok_ptr->type == SCC_TOK_L_PAREN) {
|
||||||
@@ -476,6 +484,7 @@ static scc_ast_expr_t *parse_cast_expression(scc_parser_t *parser) {
|
|||||||
if (type) {
|
if (type) {
|
||||||
// 消耗了类型名后,下一个应该是 ')'
|
// 消耗了类型名后,下一个应该是 ')'
|
||||||
if (scc_parser_consume_if(parser, SCC_TOK_R_PAREN)) {
|
if (scc_parser_consume_if(parser, SCC_TOK_R_PAREN)) {
|
||||||
|
LOG_TRACE(" detected type cast");
|
||||||
// 是类型转换,解析后面的 cast-expression(注意 cast-expression
|
// 是类型转换,解析后面的 cast-expression(注意 cast-expression
|
||||||
// 可以嵌套)
|
// 可以嵌套)
|
||||||
scc_ast_expr_t *operand = parse_cast_expression(parser);
|
scc_ast_expr_t *operand = parse_cast_expression(parser);
|
||||||
@@ -524,6 +533,7 @@ static scc_ast_expr_t *parse_unary_expression(scc_parser_t *parser) {
|
|||||||
& * + - ~ !
|
& * + - ~ !
|
||||||
*/
|
*/
|
||||||
const scc_lexer_tok_t *tok_ptr = scc_parser_peek(parser);
|
const scc_lexer_tok_t *tok_ptr = scc_parser_peek(parser);
|
||||||
|
LOG_TRACE("parse_unary_expression()");
|
||||||
if (!tok_ptr)
|
if (!tok_ptr)
|
||||||
return nullptr;
|
return nullptr;
|
||||||
|
|
||||||
@@ -543,6 +553,7 @@ static scc_ast_expr_t *parse_unary_expression(scc_parser_t *parser) {
|
|||||||
if (!scc_parser_next_consume(parser, &tok))
|
if (!scc_parser_next_consume(parser, &tok))
|
||||||
return nullptr;
|
return nullptr;
|
||||||
scc_ast_expr_op_t op = map_token_to_unary_op(tok.type, true);
|
scc_ast_expr_op_t op = map_token_to_unary_op(tok.type, true);
|
||||||
|
LOG_TRACE(" unary op=%d", op);
|
||||||
scc_pos_t pos = tok.loc;
|
scc_pos_t pos = tok.loc;
|
||||||
scc_lexer_tok_drop(&tok);
|
scc_lexer_tok_drop(&tok);
|
||||||
|
|
||||||
@@ -574,6 +585,7 @@ static scc_ast_expr_t *parse_unary_expression(scc_parser_t *parser) {
|
|||||||
|
|
||||||
// sizeof 表达式(特殊处理两种形式)
|
// sizeof 表达式(特殊处理两种形式)
|
||||||
static scc_ast_expr_t *parse_sizeof_expression(scc_parser_t *parser) {
|
static scc_ast_expr_t *parse_sizeof_expression(scc_parser_t *parser) {
|
||||||
|
LOG_TRACE("parse_sizeof_expression()");
|
||||||
scc_lexer_tok_t tok_ptr;
|
scc_lexer_tok_t tok_ptr;
|
||||||
if (!scc_parser_next_consume(parser, &tok_ptr) ||
|
if (!scc_parser_next_consume(parser, &tok_ptr) ||
|
||||||
tok_ptr.type != SCC_TOK_SIZEOF) {
|
tok_ptr.type != SCC_TOK_SIZEOF) {
|
||||||
@@ -606,6 +618,7 @@ static scc_ast_expr_t *parse_sizeof_expression(scc_parser_t *parser) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
Assert(type_name != nullptr);
|
Assert(type_name != nullptr);
|
||||||
|
LOG_TRACE(" sizeof(type)");
|
||||||
scc_ast_expr_sizeof_init(expr, type_name, nullptr, pos);
|
scc_ast_expr_sizeof_init(expr, type_name, nullptr, pos);
|
||||||
return expr;
|
return expr;
|
||||||
}
|
}
|
||||||
@@ -613,6 +626,7 @@ next:
|
|||||||
// 尝试解析 sizeof unary-expression
|
// 尝试解析 sizeof unary-expression
|
||||||
scc_ast_expr_t *operand = parse_unary_expression(parser);
|
scc_ast_expr_t *operand = parse_unary_expression(parser);
|
||||||
if (operand != nullptr) {
|
if (operand != nullptr) {
|
||||||
|
LOG_TRACE(" sizeof(expr)");
|
||||||
scc_ast_expr_sizeof_init(expr, nullptr, operand, pos);
|
scc_ast_expr_sizeof_init(expr, nullptr, operand, pos);
|
||||||
return expr;
|
return expr;
|
||||||
}
|
}
|
||||||
@@ -623,6 +637,7 @@ next:
|
|||||||
|
|
||||||
// 后缀表达式
|
// 后缀表达式
|
||||||
static scc_ast_expr_t *parse_postfix_expression(scc_parser_t *parser) {
|
static scc_ast_expr_t *parse_postfix_expression(scc_parser_t *parser) {
|
||||||
|
LOG_TRACE("parse_postfix_expression()");
|
||||||
scc_ast_expr_t *left = parse_primary_expression(parser);
|
scc_ast_expr_t *left = parse_primary_expression(parser);
|
||||||
const scc_lexer_tok_t *tok_ptr = nullptr;
|
const scc_lexer_tok_t *tok_ptr = nullptr;
|
||||||
scc_pos_t pos = scc_pos_create();
|
scc_pos_t pos = scc_pos_create();
|
||||||
@@ -658,6 +673,7 @@ static scc_ast_expr_t *parse_postfix_expression(scc_parser_t *parser) {
|
|||||||
switch (tok_ptr->type) {
|
switch (tok_ptr->type) {
|
||||||
case SCC_TOK_L_BRACKET: // left[expr]
|
case SCC_TOK_L_BRACKET: // left[expr]
|
||||||
{
|
{
|
||||||
|
LOG_TRACE(" postfix: array subscript");
|
||||||
if (!scc_parser_next_consume(parser, nullptr))
|
if (!scc_parser_next_consume(parser, nullptr))
|
||||||
return left;
|
return left;
|
||||||
pos = left->base.loc;
|
pos = left->base.loc;
|
||||||
@@ -681,6 +697,7 @@ static scc_ast_expr_t *parse_postfix_expression(scc_parser_t *parser) {
|
|||||||
}
|
}
|
||||||
case SCC_TOK_L_PAREN: // left(args)
|
case SCC_TOK_L_PAREN: // left(args)
|
||||||
{
|
{
|
||||||
|
LOG_TRACE(" postfix: function call");
|
||||||
if (!scc_parser_next_consume(parser, nullptr))
|
if (!scc_parser_next_consume(parser, nullptr))
|
||||||
goto done;
|
goto done;
|
||||||
pos = left->base.loc;
|
pos = left->base.loc;
|
||||||
@@ -718,6 +735,8 @@ static scc_ast_expr_t *parse_postfix_expression(scc_parser_t *parser) {
|
|||||||
}
|
}
|
||||||
case SCC_TOK_DOT:
|
case SCC_TOK_DOT:
|
||||||
case SCC_TOK_DEREF: {
|
case SCC_TOK_DEREF: {
|
||||||
|
LOG_TRACE(" postfix: member access (%s)",
|
||||||
|
tok_ptr->type == SCC_TOK_DOT ? "." : "->");
|
||||||
scc_lexer_tok_t op_tok;
|
scc_lexer_tok_t op_tok;
|
||||||
if (!scc_parser_next_consume(parser, &op_tok))
|
if (!scc_parser_next_consume(parser, &op_tok))
|
||||||
goto done;
|
goto done;
|
||||||
@@ -751,6 +770,7 @@ static scc_ast_expr_t *parse_postfix_expression(scc_parser_t *parser) {
|
|||||||
case SCC_TOK_ADD_ADD: // left++
|
case SCC_TOK_ADD_ADD: // left++
|
||||||
case SCC_TOK_SUB_SUB: // left--
|
case SCC_TOK_SUB_SUB: // left--
|
||||||
{
|
{
|
||||||
|
LOG_TRACE(" postfix: inc/dec");
|
||||||
scc_lexer_tok_t op_tok;
|
scc_lexer_tok_t op_tok;
|
||||||
if (!scc_parser_next_consume(parser, &op_tok))
|
if (!scc_parser_next_consume(parser, &op_tok))
|
||||||
goto done;
|
goto done;
|
||||||
@@ -781,6 +801,7 @@ static scc_ast_expr_t *parse_primary_expression(scc_parser_t *parser) {
|
|||||||
string-literal
|
string-literal
|
||||||
( expression )
|
( expression )
|
||||||
*/
|
*/
|
||||||
|
LOG_TRACE("parse_primary_expression()");
|
||||||
const scc_lexer_tok_t *tok_ptr = scc_parser_peek(parser);
|
const scc_lexer_tok_t *tok_ptr = scc_parser_peek(parser);
|
||||||
if (!tok_ptr)
|
if (!tok_ptr)
|
||||||
return nullptr;
|
return nullptr;
|
||||||
@@ -789,6 +810,7 @@ static scc_ast_expr_t *parse_primary_expression(scc_parser_t *parser) {
|
|||||||
scc_ast_expr_t *expr = nullptr;
|
scc_ast_expr_t *expr = nullptr;
|
||||||
switch (tok_ptr->type) {
|
switch (tok_ptr->type) {
|
||||||
case SCC_TOK_IDENT: {
|
case SCC_TOK_IDENT: {
|
||||||
|
LOG_TRACE(" primary: identifier");
|
||||||
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_module);
|
expr = SCC_AST_ALLOC_EXPR(parser->ast_module);
|
||||||
@@ -801,6 +823,7 @@ static scc_ast_expr_t *parse_primary_expression(scc_parser_t *parser) {
|
|||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case SCC_TOK_INT_LITERAL: {
|
case SCC_TOK_INT_LITERAL: {
|
||||||
|
LOG_TRACE(" primary: 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_module);
|
expr = SCC_AST_ALLOC_EXPR(parser->ast_module);
|
||||||
@@ -813,6 +836,7 @@ static scc_ast_expr_t *parse_primary_expression(scc_parser_t *parser) {
|
|||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case SCC_TOK_FLOAT_LITERAL: {
|
case SCC_TOK_FLOAT_LITERAL: {
|
||||||
|
LOG_TRACE(" primary: 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_module);
|
expr = SCC_AST_ALLOC_EXPR(parser->ast_module);
|
||||||
@@ -825,6 +849,7 @@ static scc_ast_expr_t *parse_primary_expression(scc_parser_t *parser) {
|
|||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case SCC_TOK_CHAR_LITERAL: {
|
case SCC_TOK_CHAR_LITERAL: {
|
||||||
|
LOG_TRACE(" primary: 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_module);
|
expr = SCC_AST_ALLOC_EXPR(parser->ast_module);
|
||||||
@@ -837,6 +862,7 @@ static scc_ast_expr_t *parse_primary_expression(scc_parser_t *parser) {
|
|||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case SCC_TOK_STRING_LITERAL: {
|
case SCC_TOK_STRING_LITERAL: {
|
||||||
|
LOG_TRACE(" primary: string literal");
|
||||||
scc_str_t string = scc_str_empty();
|
scc_str_t string = scc_str_empty();
|
||||||
scc_lexer_tok_t tok;
|
scc_lexer_tok_t tok;
|
||||||
while (1) {
|
while (1) {
|
||||||
@@ -863,6 +889,7 @@ static scc_ast_expr_t *parse_primary_expression(scc_parser_t *parser) {
|
|||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case SCC_TOK_L_PAREN:
|
case SCC_TOK_L_PAREN:
|
||||||
|
LOG_TRACE(" primary: parenthesized expression");
|
||||||
scc_parser_next_consume(parser, nullptr);
|
scc_parser_next_consume(parser, nullptr);
|
||||||
expr = scc_parse_expression(parser);
|
expr = scc_parse_expression(parser);
|
||||||
if (!scc_parser_consume_if(parser, SCC_TOK_R_PAREN)) {
|
if (!scc_parser_consume_if(parser, SCC_TOK_R_PAREN)) {
|
||||||
@@ -882,6 +909,7 @@ static scc_ast_expr_t *parse_primary_expression(scc_parser_t *parser) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
scc_ast_expr_t *scc_parse_expression(scc_parser_t *parser) {
|
scc_ast_expr_t *scc_parse_expression(scc_parser_t *parser) {
|
||||||
|
LOG_DEBUG("scc_parse_expression()");
|
||||||
scc_ast_expr_t *left = scc_parse_assignment_expression(parser);
|
scc_ast_expr_t *left = scc_parse_assignment_expression(parser);
|
||||||
if (!left)
|
if (!left)
|
||||||
return nullptr;
|
return nullptr;
|
||||||
@@ -892,6 +920,7 @@ scc_ast_expr_t *scc_parse_expression(scc_parser_t *parser) {
|
|||||||
if (tok_ptr == nullptr || tok_ptr->type != SCC_TOK_COMMA) {
|
if (tok_ptr == nullptr || tok_ptr->type != SCC_TOK_COMMA) {
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
LOG_TRACE(" comma expression");
|
||||||
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);
|
||||||
|
|
||||||
@@ -909,6 +938,7 @@ scc_ast_expr_t *scc_parse_expression(scc_parser_t *parser) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
scc_ast_expr_t *scc_parser_constant_expression(scc_parser_t *parser) {
|
scc_ast_expr_t *scc_parser_constant_expression(scc_parser_t *parser) {
|
||||||
|
LOG_DEBUG("scc_parser_constant_expression()");
|
||||||
// TODO check constant
|
// TODO check constant
|
||||||
return parse_conditional_expression(parser);
|
return parse_conditional_expression(parser);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -46,12 +46,14 @@ A.2.3 Statements
|
|||||||
break ;
|
break ;
|
||||||
return expression(opt) ;
|
return expression(opt) ;
|
||||||
*/
|
*/
|
||||||
|
#include <scc_parser_log.h>
|
||||||
|
|
||||||
#include <parser_utils.h>
|
#include <parser_utils.h>
|
||||||
#include <scc_ast_utils.h>
|
#include <scc_ast_utils.h>
|
||||||
#include <scc_parser.h>
|
#include <scc_parser.h>
|
||||||
|
|
||||||
static inline scc_ast_expr_t *ast_parse_paren_expression(scc_parser_t *parser) {
|
static inline scc_ast_expr_t *ast_parse_paren_expression(scc_parser_t *parser) {
|
||||||
|
LOG_TRACE("ast_parse_paren_expression()");
|
||||||
if (!scc_parser_consume_if(parser, SCC_TOK_L_PAREN)) {
|
if (!scc_parser_consume_if(parser, SCC_TOK_L_PAREN)) {
|
||||||
SCC_ERROR(scc_parser_got_current_pos(parser),
|
SCC_ERROR(scc_parser_got_current_pos(parser),
|
||||||
"Expected '(' before like `( expression )` .");
|
"Expected '(' before like `( expression )` .");
|
||||||
@@ -68,6 +70,7 @@ static inline scc_ast_expr_t *ast_parse_paren_expression(scc_parser_t *parser) {
|
|||||||
|
|
||||||
static scc_ast_stmt_t *parse_label_statement(scc_parser_t *parser,
|
static scc_ast_stmt_t *parse_label_statement(scc_parser_t *parser,
|
||||||
scc_pos_t pos) {
|
scc_pos_t pos) {
|
||||||
|
LOG_TRACE("parse_label_statement()");
|
||||||
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)) {
|
||||||
return nullptr;
|
return nullptr;
|
||||||
@@ -85,12 +88,16 @@ static scc_ast_stmt_t *parse_label_statement(scc_parser_t *parser,
|
|||||||
|
|
||||||
scc_ast_stmt_t *stmt = SCC_AST_ALLOC_STMT(parser->ast_module);
|
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_ast_module_intern(parser->ast_module, 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;
|
||||||
}
|
}
|
||||||
|
|
||||||
static scc_ast_stmt_t *parse_case_statement(scc_parser_t *parser,
|
static scc_ast_stmt_t *parse_case_statement(scc_parser_t *parser,
|
||||||
scc_pos_t pos) {
|
scc_pos_t pos) {
|
||||||
|
LOG_TRACE("parse_case_statement()");
|
||||||
if (!scc_parser_consume_if(parser, SCC_TOK_CASE)) {
|
if (!scc_parser_consume_if(parser, SCC_TOK_CASE)) {
|
||||||
return nullptr;
|
return nullptr;
|
||||||
}
|
}
|
||||||
@@ -121,6 +128,7 @@ static scc_ast_stmt_t *parse_case_statement(scc_parser_t *parser,
|
|||||||
|
|
||||||
static scc_ast_stmt_t *parse_default_statement(scc_parser_t *parser,
|
static scc_ast_stmt_t *parse_default_statement(scc_parser_t *parser,
|
||||||
scc_pos_t pos) {
|
scc_pos_t pos) {
|
||||||
|
LOG_TRACE("parse_default_statement()");
|
||||||
if (!scc_parser_consume_if(parser, SCC_TOK_DEFAULT)) {
|
if (!scc_parser_consume_if(parser, SCC_TOK_DEFAULT)) {
|
||||||
return nullptr;
|
return nullptr;
|
||||||
}
|
}
|
||||||
@@ -143,6 +151,7 @@ static scc_ast_stmt_t *parse_default_statement(scc_parser_t *parser,
|
|||||||
|
|
||||||
static scc_ast_stmt_t *parse_compound_statement(scc_parser_t *parser,
|
static scc_ast_stmt_t *parse_compound_statement(scc_parser_t *parser,
|
||||||
scc_pos_t pos) {
|
scc_pos_t pos) {
|
||||||
|
LOG_DEBUG("parse_compound_statement()");
|
||||||
if (!scc_parser_consume_if(parser, SCC_TOK_L_BRACE)) {
|
if (!scc_parser_consume_if(parser, SCC_TOK_L_BRACE)) {
|
||||||
return nullptr;
|
return nullptr;
|
||||||
}
|
}
|
||||||
@@ -174,6 +183,7 @@ static scc_ast_stmt_t *parse_compound_statement(scc_parser_t *parser,
|
|||||||
}
|
}
|
||||||
|
|
||||||
static scc_ast_stmt_t *parse_if_statement(scc_parser_t *parser, scc_pos_t pos) {
|
static scc_ast_stmt_t *parse_if_statement(scc_parser_t *parser, scc_pos_t pos) {
|
||||||
|
LOG_DEBUG("parse_if_statement()");
|
||||||
if (!scc_parser_consume_if(parser, SCC_TOK_IF)) {
|
if (!scc_parser_consume_if(parser, SCC_TOK_IF)) {
|
||||||
return nullptr;
|
return nullptr;
|
||||||
}
|
}
|
||||||
@@ -195,6 +205,7 @@ static scc_ast_stmt_t *parse_if_statement(scc_parser_t *parser, scc_pos_t pos) {
|
|||||||
|
|
||||||
static scc_ast_stmt_t *parse_switch_statement(scc_parser_t *parser,
|
static scc_ast_stmt_t *parse_switch_statement(scc_parser_t *parser,
|
||||||
scc_pos_t pos) {
|
scc_pos_t pos) {
|
||||||
|
LOG_DEBUG("parse_switch_statement()");
|
||||||
if (!scc_parser_consume_if(parser, SCC_TOK_SWITCH)) {
|
if (!scc_parser_consume_if(parser, SCC_TOK_SWITCH)) {
|
||||||
return nullptr;
|
return nullptr;
|
||||||
}
|
}
|
||||||
@@ -213,6 +224,7 @@ static scc_ast_stmt_t *parse_switch_statement(scc_parser_t *parser,
|
|||||||
|
|
||||||
static scc_ast_stmt_t *parse_while_statement(scc_parser_t *parser,
|
static scc_ast_stmt_t *parse_while_statement(scc_parser_t *parser,
|
||||||
scc_pos_t pos) {
|
scc_pos_t pos) {
|
||||||
|
LOG_DEBUG("parse_while_statement()");
|
||||||
if (!scc_parser_consume_if(parser, SCC_TOK_WHILE)) {
|
if (!scc_parser_consume_if(parser, SCC_TOK_WHILE)) {
|
||||||
return nullptr;
|
return nullptr;
|
||||||
}
|
}
|
||||||
@@ -231,6 +243,7 @@ static scc_ast_stmt_t *parse_while_statement(scc_parser_t *parser,
|
|||||||
|
|
||||||
static scc_ast_stmt_t *parse_do_while_statement(scc_parser_t *parser,
|
static scc_ast_stmt_t *parse_do_while_statement(scc_parser_t *parser,
|
||||||
scc_pos_t pos) {
|
scc_pos_t pos) {
|
||||||
|
LOG_DEBUG("parse_do_while_statement()");
|
||||||
if (!scc_parser_consume_if(parser, SCC_TOK_DO)) {
|
if (!scc_parser_consume_if(parser, SCC_TOK_DO)) {
|
||||||
return nullptr;
|
return nullptr;
|
||||||
}
|
}
|
||||||
@@ -259,6 +272,7 @@ static scc_ast_stmt_t *parse_do_while_statement(scc_parser_t *parser,
|
|||||||
|
|
||||||
static scc_ast_stmt_t *parse_for_statement(scc_parser_t *parser,
|
static scc_ast_stmt_t *parse_for_statement(scc_parser_t *parser,
|
||||||
scc_pos_t pos) {
|
scc_pos_t pos) {
|
||||||
|
LOG_DEBUG("parse_for_statement()");
|
||||||
if (!scc_parser_consume_if(parser, SCC_TOK_FOR)) {
|
if (!scc_parser_consume_if(parser, SCC_TOK_FOR)) {
|
||||||
return nullptr;
|
return nullptr;
|
||||||
}
|
}
|
||||||
@@ -314,12 +328,17 @@ 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) {
|
||||||
|
LOG_DEBUG("parse_jump_statement()");
|
||||||
scc_ast_stmt_t *stmt = SCC_AST_ALLOC_STMT(parser->ast_module);
|
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_ast_module_intern(parser->ast_module, 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.");
|
||||||
@@ -343,6 +362,7 @@ static scc_ast_stmt_t *parse_jump_statement(scc_parser_t *parser,
|
|||||||
|
|
||||||
static scc_ast_stmt_t *parse_expression_statement(scc_parser_t *parser,
|
static scc_ast_stmt_t *parse_expression_statement(scc_parser_t *parser,
|
||||||
scc_pos_t pos) {
|
scc_pos_t pos) {
|
||||||
|
LOG_TRACE("parse_expression_statement()");
|
||||||
|
|
||||||
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_module);
|
scc_ast_stmt_t *stmt = SCC_AST_ALLOC_STMT(parser->ast_module);
|
||||||
@@ -366,6 +386,7 @@ static scc_ast_stmt_t *parse_expression_statement(scc_parser_t *parser,
|
|||||||
}
|
}
|
||||||
|
|
||||||
scc_ast_stmt_t *scc_parse_statement(scc_parser_t *parser) {
|
scc_ast_stmt_t *scc_parse_statement(scc_parser_t *parser) {
|
||||||
|
LOG_DEBUG("scc_parse_statement()");
|
||||||
scc_ast_stmt_t *stmt;
|
scc_ast_stmt_t *stmt;
|
||||||
const scc_lexer_tok_t *tok_ref;
|
const scc_lexer_tok_t *tok_ref;
|
||||||
tok_ref = scc_parser_peek(parser);
|
tok_ref = scc_parser_peek(parser);
|
||||||
@@ -412,6 +433,7 @@ scc_ast_stmt_t *scc_parse_statement(scc_parser_t *parser) {
|
|||||||
statement
|
statement
|
||||||
*/
|
*/
|
||||||
case SCC_TOK_L_BRACE:
|
case SCC_TOK_L_BRACE:
|
||||||
|
LOG_TRACE(" stmt: compound");
|
||||||
stmt = parse_compound_statement(parser, pos);
|
stmt = parse_compound_statement(parser, pos);
|
||||||
goto RETURN;
|
goto RETURN;
|
||||||
/*
|
/*
|
||||||
@@ -422,9 +444,11 @@ scc_ast_stmt_t *scc_parse_statement(scc_parser_t *parser) {
|
|||||||
switch ( expression ) statement
|
switch ( expression ) statement
|
||||||
*/
|
*/
|
||||||
case SCC_TOK_IF:
|
case SCC_TOK_IF:
|
||||||
|
LOG_TRACE(" stmt: if");
|
||||||
stmt = parse_if_statement(parser, pos);
|
stmt = parse_if_statement(parser, pos);
|
||||||
goto RETURN;
|
goto RETURN;
|
||||||
case SCC_TOK_SWITCH:
|
case SCC_TOK_SWITCH:
|
||||||
|
LOG_TRACE(" stmt: switch");
|
||||||
stmt = parse_switch_statement(parser, pos);
|
stmt = parse_switch_statement(parser, pos);
|
||||||
goto RETURN;
|
goto RETURN;
|
||||||
/*
|
/*
|
||||||
@@ -438,12 +462,15 @@ scc_ast_stmt_t *scc_parse_statement(scc_parser_t *parser) {
|
|||||||
statement
|
statement
|
||||||
*/
|
*/
|
||||||
case SCC_TOK_WHILE:
|
case SCC_TOK_WHILE:
|
||||||
|
LOG_TRACE(" stmt: while");
|
||||||
stmt = parse_while_statement(parser, pos);
|
stmt = parse_while_statement(parser, pos);
|
||||||
goto RETURN;
|
goto RETURN;
|
||||||
case SCC_TOK_DO:
|
case SCC_TOK_DO:
|
||||||
|
LOG_TRACE(" stmt: do-while");
|
||||||
stmt = parse_do_while_statement(parser, pos);
|
stmt = parse_do_while_statement(parser, pos);
|
||||||
goto RETURN;
|
goto RETURN;
|
||||||
case SCC_TOK_FOR:
|
case SCC_TOK_FOR:
|
||||||
|
LOG_TRACE(" stmt: for");
|
||||||
stmt = parse_for_statement(parser, pos);
|
stmt = parse_for_statement(parser, pos);
|
||||||
goto RETURN;
|
goto RETURN;
|
||||||
/*
|
/*
|
||||||
@@ -455,9 +482,19 @@ scc_ast_stmt_t *scc_parse_statement(scc_parser_t *parser) {
|
|||||||
return expression(opt) ;
|
return expression(opt) ;
|
||||||
*/
|
*/
|
||||||
case SCC_TOK_GOTO:
|
case SCC_TOK_GOTO:
|
||||||
|
LOG_TRACE(" stmt: goto");
|
||||||
|
stmt = parse_jump_statement(parser, pos);
|
||||||
|
goto RETURN;
|
||||||
case SCC_TOK_CONTINUE:
|
case SCC_TOK_CONTINUE:
|
||||||
|
LOG_TRACE(" stmt: continue");
|
||||||
|
stmt = parse_jump_statement(parser, pos);
|
||||||
|
goto RETURN;
|
||||||
case SCC_TOK_BREAK:
|
case SCC_TOK_BREAK:
|
||||||
|
LOG_TRACE(" stmt: break");
|
||||||
|
stmt = parse_jump_statement(parser, pos);
|
||||||
|
goto RETURN;
|
||||||
case SCC_TOK_RETURN:
|
case SCC_TOK_RETURN:
|
||||||
|
LOG_TRACE(" stmt: return");
|
||||||
stmt = parse_jump_statement(parser, pos);
|
stmt = parse_jump_statement(parser, pos);
|
||||||
goto RETURN;
|
goto RETURN;
|
||||||
default:
|
default:
|
||||||
|
|||||||
@@ -155,6 +155,7 @@ EXAMPLE The constructions
|
|||||||
[ constant-expression ]
|
[ constant-expression ]
|
||||||
. identifier
|
. identifier
|
||||||
*/
|
*/
|
||||||
|
#include <scc_parser_log.h>
|
||||||
|
|
||||||
#include <parser_utils.h>
|
#include <parser_utils.h>
|
||||||
#include <scc_parse_type.h>
|
#include <scc_parse_type.h>
|
||||||
@@ -186,6 +187,7 @@ parse_direct_abstract_declarator(scc_parser_t *parser,
|
|||||||
* - 函数说明符 (inline)
|
* - 函数说明符 (inline)
|
||||||
*/
|
*/
|
||||||
cbool scc_parse_is_decl_specifier_start(scc_parser_t *parser) {
|
cbool scc_parse_is_decl_specifier_start(scc_parser_t *parser) {
|
||||||
|
LOG_TRACE("scc_parse_is_decl_specifier_start()");
|
||||||
const scc_lexer_tok_t *tok_ptr = scc_parser_peek(parser);
|
const scc_lexer_tok_t *tok_ptr = scc_parser_peek(parser);
|
||||||
if (tok_ptr == nullptr) {
|
if (tok_ptr == nullptr) {
|
||||||
return false;
|
return false;
|
||||||
@@ -230,6 +232,7 @@ cbool scc_parse_is_decl_specifier_start(scc_parser_t *parser) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
cbool scc_parse_is_type_specifier_start(scc_parser_t *parser) {
|
cbool scc_parse_is_type_specifier_start(scc_parser_t *parser) {
|
||||||
|
LOG_TRACE("scc_parse_is_type_specifier_start()");
|
||||||
const scc_lexer_tok_t *tok_ptr = scc_parser_peek(parser);
|
const scc_lexer_tok_t *tok_ptr = scc_parser_peek(parser);
|
||||||
if (tok_ptr == nullptr) {
|
if (tok_ptr == nullptr) {
|
||||||
return false;
|
return false;
|
||||||
@@ -551,7 +554,8 @@ 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_ast_module_intern(parser->ast_module, 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,7 +585,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_module_alloc_type(parser->ast_module);
|
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_module);
|
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;
|
||||||
@@ -620,6 +625,8 @@ static scc_ast_qual_type_t *parse_record_type(scc_parser_t *parser,
|
|||||||
|
|
||||||
static scc_ast_qual_type_t *
|
static scc_ast_qual_type_t *
|
||||||
parse_struct_union_type(scc_parser_t *parser, scc_ast_node_kind_t type_kind) {
|
parse_struct_union_type(scc_parser_t *parser, scc_ast_node_kind_t type_kind) {
|
||||||
|
LOG_DEBUG("parse_struct_union_type(kind=%s)",
|
||||||
|
type_kind == SCC_AST_TYPE_STRUCT ? "struct" : "union");
|
||||||
/*
|
/*
|
||||||
(6.7.2.1)
|
(6.7.2.1)
|
||||||
struct-or-union-specifier:
|
struct-or-union-specifier:
|
||||||
@@ -699,6 +706,7 @@ parse_struct_union_type(scc_parser_t *parser, scc_ast_node_kind_t type_kind) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
static scc_ast_qual_type_t *parse_enum_type(scc_parser_t *parser) {
|
static scc_ast_qual_type_t *parse_enum_type(scc_parser_t *parser) {
|
||||||
|
LOG_DEBUG("parse_enum_type()");
|
||||||
/*
|
/*
|
||||||
(6.7.2.2)
|
(6.7.2.2)
|
||||||
enum-specifier:
|
enum-specifier:
|
||||||
@@ -749,9 +757,11 @@ 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_module);
|
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(
|
||||||
scc_ast_module_intern(parser->ast_module, scc_str_as_cstr(&tok.lexeme)), enum_item_init,
|
enum_item_decl, type,
|
||||||
tok.loc);
|
scc_ast_module_intern(parser->ast_module,
|
||||||
|
scc_str_as_cstr(&tok.lexeme)),
|
||||||
|
enum_item_init, tok.loc);
|
||||||
scc_vec_push(decl->record.fields, enum_item_decl);
|
scc_vec_push(decl->record.fields, enum_item_decl);
|
||||||
|
|
||||||
tok_ptr = scc_parser_peek(parser);
|
tok_ptr = scc_parser_peek(parser);
|
||||||
@@ -788,6 +798,7 @@ static scc_ast_qual_type_t *parse_enum_type(scc_parser_t *parser) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
static scc_ast_qual_type_t *parse_type_specifier(scc_parser_t *parser) {
|
static scc_ast_qual_type_t *parse_type_specifier(scc_parser_t *parser) {
|
||||||
|
LOG_TRACE("parse_type_specifier()");
|
||||||
type_spec_info_t info = {0};
|
type_spec_info_t info = {0};
|
||||||
if (!scc_parse_is_type_specifier_start(parser))
|
if (!scc_parse_is_type_specifier_start(parser))
|
||||||
return nullptr;
|
return nullptr;
|
||||||
@@ -927,6 +938,7 @@ duplicate_error:
|
|||||||
static scc_ast_qual_type_t *
|
static scc_ast_qual_type_t *
|
||||||
parse_pointer(scc_parser_t *parser, scc_ast_qual_type_t *pointee,
|
parse_pointer(scc_parser_t *parser, scc_ast_qual_type_t *pointee,
|
||||||
scc_ast_qual_type_t **delay_pointee_ptr) {
|
scc_ast_qual_type_t **delay_pointee_ptr) {
|
||||||
|
LOG_TRACE("parse_pointer()");
|
||||||
/*
|
/*
|
||||||
pointer:
|
pointer:
|
||||||
* type-qualifier-list(opt)
|
* type-qualifier-list(opt)
|
||||||
@@ -955,6 +967,7 @@ parse_pointer(scc_parser_t *parser, scc_ast_qual_type_t *pointee,
|
|||||||
|
|
||||||
static void parse_parameter_type_list(scc_parser_t *parser,
|
static void parse_parameter_type_list(scc_parser_t *parser,
|
||||||
scc_ast_decl_vec_t *params) {
|
scc_ast_decl_vec_t *params) {
|
||||||
|
LOG_TRACE("parse_parameter_type_list()");
|
||||||
/*
|
/*
|
||||||
(6.7.5) parameter-type-list:
|
(6.7.5) parameter-type-list:
|
||||||
parameter-list
|
parameter-list
|
||||||
@@ -1110,6 +1123,7 @@ static scc_ast_qual_type_t *
|
|||||||
parse_direct_declarator(scc_parser_t *parser, scc_ast_qual_type_t *base,
|
parse_direct_declarator(scc_parser_t *parser, scc_ast_qual_type_t *base,
|
||||||
scc_ast_qual_type_t **delay_pointee_ptr,
|
scc_ast_qual_type_t **delay_pointee_ptr,
|
||||||
scc_lexer_tok_t *tok_ident) {
|
scc_lexer_tok_t *tok_ident) {
|
||||||
|
LOG_TRACE("parse_direct_declarator()");
|
||||||
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_module_alloc_type(parser->ast_module);
|
scc_ast_canon_type_t *canon = scc_ast_module_alloc_type(parser->ast_module);
|
||||||
@@ -1200,6 +1214,7 @@ static scc_ast_qual_type_t *
|
|||||||
parse_direct_abstract_declarator(scc_parser_t *parser,
|
parse_direct_abstract_declarator(scc_parser_t *parser,
|
||||||
scc_ast_qual_type_t *base,
|
scc_ast_qual_type_t *base,
|
||||||
scc_ast_qual_type_t **delay_pointee_ptr) {
|
scc_ast_qual_type_t **delay_pointee_ptr) {
|
||||||
|
LOG_TRACE("parse_direct_abstract_declarator()");
|
||||||
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_module_alloc_type(parser->ast_module);
|
scc_ast_canon_type_t *canon = scc_ast_module_alloc_type(parser->ast_module);
|
||||||
@@ -1250,6 +1265,7 @@ parse_direct_abstract_declarator(scc_parser_t *parser,
|
|||||||
|
|
||||||
scc_ast_decl_t *scc_parse_declarator(scc_parser_t *parser,
|
scc_ast_decl_t *scc_parse_declarator(scc_parser_t *parser,
|
||||||
scc_ast_qual_type_t *type) {
|
scc_ast_qual_type_t *type) {
|
||||||
|
LOG_DEBUG("scc_parse_declarator()");
|
||||||
scc_lexer_tok_t decl_name_tok = {0};
|
scc_lexer_tok_t decl_name_tok = {0};
|
||||||
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);
|
||||||
@@ -1260,8 +1276,10 @@ scc_ast_decl_t *scc_parse_declarator(scc_parser_t *parser,
|
|||||||
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 =
|
||||||
? scc_ast_module_intern(parser->ast_module, scc_str_as_cstr(&decl_name_tok.lexeme))
|
decl_name_tok.type == SCC_TOK_IDENT
|
||||||
|
? 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) {
|
||||||
@@ -1297,6 +1315,7 @@ scc_ast_decl_t *scc_parse_declarator(scc_parser_t *parser,
|
|||||||
}
|
}
|
||||||
|
|
||||||
scc_ast_qual_type_t *scc_parse_declaration_specifiers(scc_parser_t *parser) {
|
scc_ast_qual_type_t *scc_parse_declaration_specifiers(scc_parser_t *parser) {
|
||||||
|
LOG_DEBUG("scc_parse_declaration_specifiers()");
|
||||||
if (!scc_parse_is_decl_specifier_start(parser)) {
|
if (!scc_parse_is_decl_specifier_start(parser)) {
|
||||||
return nullptr;
|
return nullptr;
|
||||||
}
|
}
|
||||||
@@ -1319,6 +1338,7 @@ scc_ast_qual_type_t *scc_parse_declaration_specifiers(scc_parser_t *parser) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
scc_ast_qual_type_t *scc_parse_type_name(scc_parser_t *parser) {
|
scc_ast_qual_type_t *scc_parse_type_name(scc_parser_t *parser) {
|
||||||
|
LOG_DEBUG("scc_parse_type_name()");
|
||||||
if (!(scc_parse_is_type_specifier_start(parser) ||
|
if (!(scc_parse_is_type_specifier_start(parser) ||
|
||||||
scc_parse_is_type_qualifier_start(parser))) {
|
scc_parse_is_type_qualifier_start(parser))) {
|
||||||
return nullptr;
|
return nullptr;
|
||||||
|
|||||||
@@ -1,3 +1,6 @@
|
|||||||
|
#define __SCC_PARSER_LOG_IMPL__
|
||||||
|
#include <scc_parser_log.h>
|
||||||
|
|
||||||
#include <parser_utils.h>
|
#include <parser_utils.h>
|
||||||
#include <scc_parser.h>
|
#include <scc_parser.h>
|
||||||
|
|
||||||
@@ -55,6 +58,7 @@ void scc_parser_drop(scc_parser_t *parser) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
scc_ast_translation_unit_t *scc_parse_translation_unit(scc_parser_t *parser) {
|
scc_ast_translation_unit_t *scc_parse_translation_unit(scc_parser_t *parser) {
|
||||||
|
LOG_INFO("start parsing translation unit");
|
||||||
scc_ast_translation_unit_t *unit =
|
scc_ast_translation_unit_t *unit =
|
||||||
scc_malloc(sizeof(scc_ast_translation_unit_t));
|
scc_malloc(sizeof(scc_ast_translation_unit_t));
|
||||||
if (!unit)
|
if (!unit)
|
||||||
@@ -71,6 +75,8 @@ scc_ast_translation_unit_t *scc_parse_translation_unit(scc_parser_t *parser) {
|
|||||||
while (1) {
|
while (1) {
|
||||||
scc_ast_decl_t *decl = scc_parse_declaration(parser);
|
scc_ast_decl_t *decl = scc_parse_declaration(parser);
|
||||||
if (decl != nullptr) {
|
if (decl != nullptr) {
|
||||||
|
LOG_DEBUG("parsed declaration type=%d name='%s'", decl->base.type,
|
||||||
|
decl->name ? decl->name : "?");
|
||||||
scc_vec_push(unit->declarations, decl);
|
scc_vec_push(unit->declarations, decl);
|
||||||
} else {
|
} else {
|
||||||
parser->errcode = 1;
|
parser->errcode = 1;
|
||||||
|
|||||||
@@ -1,5 +1,7 @@
|
|||||||
|
#include <scc_parser_log.h>
|
||||||
|
|
||||||
#include <scc_ast_utils.h>
|
#include <scc_ast_utils.h>
|
||||||
#include <scc_pos_log.h>
|
#include <scc_parse_type.h>
|
||||||
#include <scc_sema.h>
|
#include <scc_sema.h>
|
||||||
#include <sema_symtab.h>
|
#include <sema_symtab.h>
|
||||||
|
|
||||||
@@ -159,6 +161,7 @@ static void expr_callback(scc_sema_ctx_t *sema_ctx,
|
|||||||
if (node_type == SCC_AST_UNKNOWN || node == nullptr) {
|
if (node_type == SCC_AST_UNKNOWN || node == nullptr) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
LOG_TRACE("sema_expr: type=%d", node_type);
|
||||||
scc_ast_expr_t *expr = SCC_AST_CAST_TO(scc_ast_expr_t, node);
|
scc_ast_expr_t *expr = SCC_AST_CAST_TO(scc_ast_expr_t, node);
|
||||||
if (node_type == SCC_AST_EXPR_IDENTIFIER) {
|
if (node_type == SCC_AST_EXPR_IDENTIFIER) {
|
||||||
scc_ast_node_t *sym_node =
|
scc_ast_node_t *sym_node =
|
||||||
@@ -242,6 +245,7 @@ static void stmt_callback(scc_sema_ctx_t *sema_ctx,
|
|||||||
scc_ast_node_kind_t node_type, void *node) {
|
scc_ast_node_kind_t node_type, void *node) {
|
||||||
scc_sema_symtab_t *sema_symtab = sema_ctx->context;
|
scc_sema_symtab_t *sema_symtab = sema_ctx->context;
|
||||||
|
|
||||||
|
LOG_TRACE("sema_stmt: node_type=%d", node_type);
|
||||||
if (node_type == scc_ast_stmt_t_BEGIN) {
|
if (node_type == scc_ast_stmt_t_BEGIN) {
|
||||||
if (node == nullptr) {
|
if (node == nullptr) {
|
||||||
scc_sema_symtab_enter_scope(sema_symtab);
|
scc_sema_symtab_enter_scope(sema_symtab);
|
||||||
@@ -364,6 +368,7 @@ static void decl_callback(scc_sema_ctx_t *sema_ctx,
|
|||||||
scc_ast_node_kind_t node_type, void *node) {
|
scc_ast_node_kind_t node_type, void *node) {
|
||||||
scc_sema_symtab_t *sema_symtab = sema_ctx->context;
|
scc_sema_symtab_t *sema_symtab = sema_ctx->context;
|
||||||
|
|
||||||
|
LOG_TRACE("sema_decl: node_type=%d", node_type);
|
||||||
// Function declaration scope
|
// Function declaration scope
|
||||||
// FIXME 使用 node_type 区分其他未来的scope
|
// FIXME 使用 node_type 区分其他未来的scope
|
||||||
if (node_type == scc_ast_decl_t_BEGIN) {
|
if (node_type == scc_ast_decl_t_BEGIN) {
|
||||||
@@ -447,6 +452,7 @@ static scc_ast_qual_type_t *got_type_callback(scc_sema_ctx_t *sema_ctx,
|
|||||||
}
|
}
|
||||||
|
|
||||||
void scc_sema_init(scc_sema_ctx_t *sema_ctx, scc_ast_module_t *ast_module) {
|
void scc_sema_init(scc_sema_ctx_t *sema_ctx, scc_ast_module_t *ast_module) {
|
||||||
|
LOG_DEBUG("scc_sema_init()");
|
||||||
sema_ctx->ast_module = ast_module;
|
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) {
|
||||||
|
|||||||
@@ -1,3 +1,5 @@
|
|||||||
|
#include <scc_parser_log.h>
|
||||||
|
|
||||||
#include <sema_symtab.h>
|
#include <sema_symtab.h>
|
||||||
|
|
||||||
void scc_sema_symtab_init(scc_sema_symtab_t *symtab) {
|
void scc_sema_symtab_init(scc_sema_symtab_t *symtab) {
|
||||||
@@ -45,12 +47,17 @@ void scc_sema_symtab_leave_scope(scc_sema_symtab_t *symtab) {
|
|||||||
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,
|
||||||
const char *name,
|
const char *name,
|
||||||
scc_ast_node_t *ast_node_ref) {
|
scc_ast_node_t *ast_node_ref) {
|
||||||
|
Assert(name != nullptr && "symbol name must not be null");
|
||||||
|
Assert(ast_node_ref != nullptr && "symbol node must not be null");
|
||||||
|
LOG_TRACE("symtab_add: '%s'", name);
|
||||||
return scc_hashtable_set(&symtab->current_scope->symbols, name,
|
return scc_hashtable_set(&symtab->current_scope->symbols, name,
|
||||||
ast_node_ref);
|
ast_node_ref);
|
||||||
}
|
}
|
||||||
|
|
||||||
scc_ast_node_t *scc_sema_symtab_lookup_symbol(scc_sema_symtab_t *symtab,
|
scc_ast_node_t *scc_sema_symtab_lookup_symbol(scc_sema_symtab_t *symtab,
|
||||||
const char *name) {
|
const char *name) {
|
||||||
|
Assert(name != nullptr && "lookup name must not be null");
|
||||||
|
LOG_TRACE("symtab_lookup: '%s'", name);
|
||||||
scc_ast_node_t *node = nullptr;
|
scc_ast_node_t *node = nullptr;
|
||||||
for (scc_sema_scope_t *scope = symtab->current_scope; scope != nullptr;
|
for (scc_sema_scope_t *scope = symtab->current_scope; scope != nullptr;
|
||||||
scope = scope->parent) {
|
scope = scope->parent) {
|
||||||
|
|||||||
26
libs/pproc/include/scc_pproc_log.h
Normal file
26
libs/pproc/include/scc_pproc_log.h
Normal file
@@ -0,0 +1,26 @@
|
|||||||
|
#ifndef __SCC_PPROC_LOG_H__
|
||||||
|
#define __SCC_PPROC_LOG_H__
|
||||||
|
|
||||||
|
typedef struct logger logger_t;
|
||||||
|
extern logger_t __scc_pproc_log;
|
||||||
|
extern logger_t __scc_pproc_user;
|
||||||
|
|
||||||
|
#define SCC_LOG_HANDLER &__scc_pproc_user
|
||||||
|
#define LOG_DEFAULT_HANDLER &__scc_pproc_log
|
||||||
|
#include <scc_log.h>
|
||||||
|
|
||||||
|
#ifdef __SCC_PPROC_LOG_IMPL__
|
||||||
|
logger_t __scc_pproc_log = {
|
||||||
|
.name = "pproc",
|
||||||
|
.level = LOG_LEVEL_ALL,
|
||||||
|
.handler = log_default_handler,
|
||||||
|
};
|
||||||
|
|
||||||
|
logger_t __scc_pproc_user = {
|
||||||
|
.name = "pproc",
|
||||||
|
.level = LOG_LEVEL_ALL,
|
||||||
|
.user_handler = scc_log_handler,
|
||||||
|
};
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#endif
|
||||||
@@ -1,3 +1,5 @@
|
|||||||
|
#include <scc_pproc_log.h>
|
||||||
|
|
||||||
#include <pproc_expand.h>
|
#include <pproc_expand.h>
|
||||||
#include <scc_core_ring.h>
|
#include <scc_core_ring.h>
|
||||||
#include <scc_lexer_utils.h>
|
#include <scc_lexer_utils.h>
|
||||||
@@ -353,7 +355,7 @@ void scc_pproc_handle_directive(scc_pproc_t *pp) {
|
|||||||
goto ERROR;
|
goto ERROR;
|
||||||
case SCC_PP_TOK_EMBED:
|
case SCC_PP_TOK_EMBED:
|
||||||
goto ERROR;
|
goto ERROR;
|
||||||
#define __SCC_PPROC_LOG_PNT(func_name) \
|
#define __SCC_PPROC_LOG_ERR() \
|
||||||
do { \
|
do { \
|
||||||
scc_lexer_tok_drop(&tok); \
|
scc_lexer_tok_drop(&tok); \
|
||||||
while (1) { \
|
while (1) { \
|
||||||
@@ -362,17 +364,33 @@ void scc_pproc_handle_directive(scc_pproc_t *pp) {
|
|||||||
return; \
|
return; \
|
||||||
} \
|
} \
|
||||||
if (scc_get_tok_subtype(tok.type) == SCC_TOK_SUBTYPE_LITERAL) { \
|
if (scc_get_tok_subtype(tok.type) == SCC_TOK_SUBTYPE_LITERAL) { \
|
||||||
func_name(tok.loc, "%s", scc_str_as_cstr(&tok.lexeme)); \
|
SCC_ERROR(tok.loc, "%s", scc_str_as_cstr(&tok.lexeme)); \
|
||||||
|
} \
|
||||||
|
scc_lexer_tok_drop(&tok); \
|
||||||
|
} \
|
||||||
|
return; \
|
||||||
|
} while (0)
|
||||||
|
|
||||||
|
#define __SCC_PPROC_LOG_WARN() \
|
||||||
|
do { \
|
||||||
|
scc_lexer_tok_drop(&tok); \
|
||||||
|
while (1) { \
|
||||||
|
ok = scc_lexer_next_non_blank(pp->cur_ring, &tok); \
|
||||||
|
if (tok.type == SCC_TOK_ENDLINE || ok == false) { \
|
||||||
|
return; \
|
||||||
|
} \
|
||||||
|
if (scc_get_tok_subtype(tok.type) == SCC_TOK_SUBTYPE_LITERAL) { \
|
||||||
|
SCC_WARN(tok.loc, "%s", scc_str_as_cstr(&tok.lexeme)); \
|
||||||
} \
|
} \
|
||||||
scc_lexer_tok_drop(&tok); \
|
scc_lexer_tok_drop(&tok); \
|
||||||
} \
|
} \
|
||||||
return; \
|
return; \
|
||||||
} while (0)
|
} while (0)
|
||||||
case SCC_PP_TOK_ERROR: {
|
case SCC_PP_TOK_ERROR: {
|
||||||
__SCC_PPROC_LOG_PNT(SCC_ERROR);
|
__SCC_PPROC_LOG_ERR();
|
||||||
}
|
}
|
||||||
case SCC_PP_TOK_WARNING: {
|
case SCC_PP_TOK_WARNING: {
|
||||||
__SCC_PPROC_LOG_PNT(SCC_WARN);
|
__SCC_PPROC_LOG_WARN();
|
||||||
}
|
}
|
||||||
case SCC_PP_TOK_PRAGMA:
|
case SCC_PP_TOK_PRAGMA:
|
||||||
SCC_WARN(tok.loc, "pragma ignored");
|
SCC_WARN(tok.loc, "pragma ignored");
|
||||||
|
|||||||
@@ -1,3 +1,5 @@
|
|||||||
|
#include <scc_pproc_log.h>
|
||||||
|
|
||||||
#include <pproc_expand.h>
|
#include <pproc_expand.h>
|
||||||
#include <scc_lexer_utils.h>
|
#include <scc_lexer_utils.h>
|
||||||
#include <scc_pproc.h>
|
#include <scc_pproc.h>
|
||||||
@@ -125,6 +127,8 @@ void scc_pproc_expand_by_src(scc_pproc_macro_table_t *macro_table,
|
|||||||
scc_lexer_tok_ring_t *output,
|
scc_lexer_tok_ring_t *output,
|
||||||
const scc_pproc_macro_t *macro,
|
const scc_pproc_macro_t *macro,
|
||||||
cbool need_keep_org_pos) {
|
cbool need_keep_org_pos) {
|
||||||
|
LOG_DEBUG("expand macro '%s' type=%s", scc_str_as_cstr(¯o->name),
|
||||||
|
macro->type == SCC_PP_MACRO_OBJECT ? "object" : "function");
|
||||||
scc_lexer_tok_vec_t expaned_buffer;
|
scc_lexer_tok_vec_t expaned_buffer;
|
||||||
scc_vec_init(expaned_buffer);
|
scc_vec_init(expaned_buffer);
|
||||||
|
|
||||||
@@ -412,6 +416,8 @@ static void concact(scc_pproc_expand_t *ctx, scc_lexer_tok_vec_t *tok_buffer,
|
|||||||
|
|
||||||
static inline void expand_function_macro(scc_pproc_expand_t *ctx,
|
static inline void expand_function_macro(scc_pproc_expand_t *ctx,
|
||||||
const scc_pproc_macro_t *macro) {
|
const scc_pproc_macro_t *macro) {
|
||||||
|
LOG_DEBUG("expand function macro '%s' (line %d)",
|
||||||
|
scc_str_as_cstr(¯o->name), ctx->call_pos.line);
|
||||||
|
|
||||||
scc_lexer_tok_vec_t tok_buffer;
|
scc_lexer_tok_vec_t tok_buffer;
|
||||||
scc_vec_init(tok_buffer);
|
scc_vec_init(tok_buffer);
|
||||||
@@ -543,6 +549,7 @@ static inline void expand_function_macro(scc_pproc_expand_t *ctx,
|
|||||||
|
|
||||||
static inline void expand_object_macro(scc_pproc_expand_t *ctx,
|
static inline void expand_object_macro(scc_pproc_expand_t *ctx,
|
||||||
const scc_pproc_macro_t *macro) {
|
const scc_pproc_macro_t *macro) {
|
||||||
|
LOG_DEBUG("expand object macro '%s'", scc_str_as_cstr(¯o->name));
|
||||||
scc_lexer_tok_vec_t tok_buffer;
|
scc_lexer_tok_vec_t tok_buffer;
|
||||||
scc_vec_init(tok_buffer);
|
scc_vec_init(tok_buffer);
|
||||||
|
|
||||||
@@ -578,13 +585,13 @@ static inline void expand_object_macro(scc_pproc_expand_t *ctx,
|
|||||||
static cbool parse_defined(scc_pproc_expand_t *expand_ctx, scc_pos_t *tok_pos) {
|
static cbool parse_defined(scc_pproc_expand_t *expand_ctx, scc_pos_t *tok_pos) {
|
||||||
scc_lexer_tok_t next_tok = {0};
|
scc_lexer_tok_t next_tok = {0};
|
||||||
if (scc_lexer_next_non_blank(expand_ctx->input, &next_tok) == false) {
|
if (scc_lexer_next_non_blank(expand_ctx->input, &next_tok) == false) {
|
||||||
SCC_ERROR(*tok_pos, "Unexpected before defined EOF");
|
SCC_ERROR(*tok_pos, "unexpected before 'defined' EOF");
|
||||||
}
|
}
|
||||||
if (next_tok.type == SCC_TOK_L_PAREN) {
|
if (next_tok.type == SCC_TOK_L_PAREN) {
|
||||||
scc_lexer_tok_drop(&next_tok);
|
scc_lexer_tok_drop(&next_tok);
|
||||||
scc_lexer_next_non_blank(expand_ctx->input, &next_tok);
|
scc_lexer_next_non_blank(expand_ctx->input, &next_tok);
|
||||||
if (scc_get_tok_subtype(next_tok.type) != SCC_TOK_SUBTYPE_IDENTIFIER) {
|
if (scc_get_tok_subtype(next_tok.type) != SCC_TOK_SUBTYPE_IDENTIFIER) {
|
||||||
SCC_ERROR(next_tok.loc, "Expected identifier before defined");
|
SCC_ERROR(next_tok.loc, "expected identifier before 'defined'");
|
||||||
scc_lexer_tok_drop(&next_tok);
|
scc_lexer_tok_drop(&next_tok);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -603,7 +610,7 @@ static cbool parse_defined(scc_pproc_expand_t *expand_ctx, scc_pos_t *tok_pos) {
|
|||||||
scc_lexer_tok_drop(&next_tok);
|
scc_lexer_tok_drop(&next_tok);
|
||||||
return false;
|
return false;
|
||||||
} else {
|
} else {
|
||||||
SCC_ERROR(next_tok.loc, "Expected ')'");
|
SCC_ERROR(next_tok.loc, "expected ')'");
|
||||||
scc_lexer_tok_drop(&next_tok);
|
scc_lexer_tok_drop(&next_tok);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -652,10 +659,14 @@ void scc_pproc_expand_macro(scc_pproc_expand_t *expand_ctx) {
|
|||||||
|
|
||||||
if (macro == nullptr || need_skip(expand_ctx, macro)) {
|
if (macro == nullptr || need_skip(expand_ctx, macro)) {
|
||||||
// FIXME maybe keyword is error or don't parse c keyword or number
|
// FIXME maybe keyword is error or don't parse c keyword or number
|
||||||
|
LOG_DEBUG("skip macro expansion for '%s'",
|
||||||
|
scc_str_as_cstr(&tok.lexeme));
|
||||||
tok.type += SCC_TOK_DISABLED;
|
tok.type += SCC_TOK_DISABLED;
|
||||||
scc_vec_push(expand_ctx->output, tok);
|
scc_vec_push(expand_ctx->output, tok);
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
LOG_DEBUG("expand macro '%s' type=%s", scc_str_as_cstr(&tok.lexeme),
|
||||||
|
macro->type == SCC_PP_MACRO_OBJECT ? "object" : "function");
|
||||||
expand_ctx->need_rescan = true;
|
expand_ctx->need_rescan = true;
|
||||||
|
|
||||||
expand_ctx->call_pos = tok.loc;
|
expand_ctx->call_pos = tok.loc;
|
||||||
|
|||||||
@@ -1,3 +1,5 @@
|
|||||||
|
#include <scc_pproc_log.h>
|
||||||
|
|
||||||
#include <scc_lexer_utils.h>
|
#include <scc_lexer_utils.h>
|
||||||
#include <scc_pproc.h>
|
#include <scc_pproc.h>
|
||||||
|
|
||||||
|
|||||||
@@ -1,3 +1,5 @@
|
|||||||
|
#include <scc_pproc_log.h>
|
||||||
|
|
||||||
#include <pproc_expand.h>
|
#include <pproc_expand.h>
|
||||||
#include <scc_core_ring.h>
|
#include <scc_core_ring.h>
|
||||||
#include <scc_path.h>
|
#include <scc_path.h>
|
||||||
@@ -39,9 +41,8 @@ static int switch_file_stack(scc_pproc_t *pp, scc_str_t *fname, scc_pos_t *pos,
|
|||||||
return -1;
|
return -1;
|
||||||
FOPEN:
|
FOPEN:
|
||||||
if ((int)scc_vec_size(pp->file_stack) >= pp->config.max_include_depth) {
|
if ((int)scc_vec_size(pp->file_stack) >= pp->config.max_include_depth) {
|
||||||
SCC_FATAL(*pos, "include depth exceeds maximum (%d)",
|
LOG_FATAL("Include depth exceeds maximum (%d)",
|
||||||
pp->config.max_include_depth);
|
pp->config.max_include_depth);
|
||||||
LOG_FATAL("Include depth is too deep...");
|
|
||||||
}
|
}
|
||||||
|
|
||||||
scc_pproc_file_t *file = scc_malloc(sizeof(scc_pproc_file_t));
|
scc_pproc_file_t *file = scc_malloc(sizeof(scc_pproc_file_t));
|
||||||
|
|||||||
@@ -1,3 +1,5 @@
|
|||||||
|
#include <scc_pproc_log.h>
|
||||||
|
|
||||||
#include <pproc_macro.h>
|
#include <pproc_macro.h>
|
||||||
|
|
||||||
// 创建宏对象
|
// 创建宏对象
|
||||||
|
|||||||
@@ -1,3 +1,6 @@
|
|||||||
|
#define __SCC_PPROC_LOG_IMPL__
|
||||||
|
#include <scc_pproc_log.h>
|
||||||
|
|
||||||
#include <pproc_expand.h>
|
#include <pproc_expand.h>
|
||||||
#include <scc_lexer.h>
|
#include <scc_lexer.h>
|
||||||
#include <scc_lexer_utils.h>
|
#include <scc_lexer_utils.h>
|
||||||
|
|||||||
@@ -626,6 +626,11 @@ static void test_c99_docs(void) {
|
|||||||
"fprintf(stderr, \"X = %d\\n\", x);\n"
|
"fprintf(stderr, \"X = %d\\n\", x);\n"
|
||||||
"puts(\"The first, second, and third items.\");\n"
|
"puts(\"The first, second, and third items.\");\n"
|
||||||
"((x>y)?puts(\"x>y\"): printf(\"x is %d but y is %d\", x, y));\n");
|
"((x>y)?puts(\"x>y\"): printf(\"x is %d but y is %d\", x, y));\n");
|
||||||
|
|
||||||
|
TEST_CASE("Typedef");
|
||||||
|
CHECK_PP_OUTPUT_EXACT(
|
||||||
|
"#define SCC_AP_DIGIT u64\ntypedef SCC_AP_DIGIT scc_ap_digit;",
|
||||||
|
"typedef u64 scc_ap_digit;");
|
||||||
}
|
}
|
||||||
|
|
||||||
#define TEST_LIST_CASE(func_name) {#func_name, func_name}
|
#define TEST_LIST_CASE(func_name) {#func_name, func_name}
|
||||||
|
|||||||
@@ -5,4 +5,5 @@ version = "0.1.0"
|
|||||||
dependencies = [
|
dependencies = [
|
||||||
{ name = "scc_core", path = "../../runtime/scc_core" },
|
{ name = "scc_core", path = "../../runtime/scc_core" },
|
||||||
{ name = "scc_utils", path = "../../runtime/scc_utils" },
|
{ name = "scc_utils", path = "../../runtime/scc_utils" },
|
||||||
|
{ name = "mcode", path = "../mcode" },
|
||||||
]
|
]
|
||||||
|
|||||||
@@ -13,6 +13,12 @@ typedef struct {
|
|||||||
scc_hashtable_t str2offset;
|
scc_hashtable_t str2offset;
|
||||||
sccf_sym_vec_t symtab;
|
sccf_sym_vec_t symtab;
|
||||||
sccf_reloc_vec_t relocs;
|
sccf_reloc_vec_t relocs;
|
||||||
|
const char *entry_symbol_name;
|
||||||
} sccf_linker_t;
|
} sccf_linker_t;
|
||||||
|
|
||||||
|
void sccf_linker_init(sccf_linker_t *linker);
|
||||||
|
void sccf_linker_add_sccf(sccf_linker_t *linker, const sccf_t *sccf);
|
||||||
|
void sccf_linker_set_entry_symbol_name(sccf_linker_t *linker, const char *name);
|
||||||
|
const sccf_t *sccf_linker_link(sccf_linker_t *linker);
|
||||||
|
|
||||||
#endif /* __SCC_FORMAT_LINKER_H__ */
|
#endif /* __SCC_FORMAT_LINKER_H__ */
|
||||||
|
|||||||
26
libs/sccf/include/sccf_log.h
Normal file
26
libs/sccf/include/sccf_log.h
Normal file
@@ -0,0 +1,26 @@
|
|||||||
|
#ifndef __SCCF_LOG_H__
|
||||||
|
#define __SCCF_LOG_H__
|
||||||
|
|
||||||
|
typedef struct logger logger_t;
|
||||||
|
extern logger_t __scc_sccf_log;
|
||||||
|
extern logger_t __scc_sccf_user;
|
||||||
|
|
||||||
|
#define SCC_LOG_HANDLER &__scc_sccf_user
|
||||||
|
#define LOG_DEFAULT_HANDLER &__scc_sccf_log
|
||||||
|
#include <scc_log.h>
|
||||||
|
|
||||||
|
#ifdef __SCCF_LOG_IMPL__
|
||||||
|
logger_t __scc_sccf_log = {
|
||||||
|
.name = "sccf",
|
||||||
|
.level = LOG_LEVEL_ALL,
|
||||||
|
.handler = log_default_handler,
|
||||||
|
};
|
||||||
|
|
||||||
|
logger_t __scc_sccf_user = {
|
||||||
|
.name = "sccf",
|
||||||
|
.level = LOG_LEVEL_ALL,
|
||||||
|
.user_handler = scc_log_handler,
|
||||||
|
};
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#endif
|
||||||
@@ -1,4 +1,5 @@
|
|||||||
#include <sccf_builder.h>
|
#include <sccf_builder.h>
|
||||||
|
#include <sccf_log.h>
|
||||||
|
|
||||||
void sccf_builder_init(sccf_builder_t *builder) {
|
void sccf_builder_init(sccf_builder_t *builder) {
|
||||||
builder->aligned = 64;
|
builder->aligned = 64;
|
||||||
|
|||||||
259
libs/sccf/src/sccf_linker.c
Normal file
259
libs/sccf/src/sccf_linker.c
Normal file
@@ -0,0 +1,259 @@
|
|||||||
|
#include <sccf_linker.h>
|
||||||
|
#include <scc_mcode.h>
|
||||||
|
#include <x86/scc_x86_patch.h>
|
||||||
|
|
||||||
|
void sccf_linker_init(sccf_linker_t *linker) {
|
||||||
|
sccf_builder_init(&linker->builder);
|
||||||
|
scc_vec_init(linker->link_sccfs);
|
||||||
|
scc_strpool_init(&linker->strpool);
|
||||||
|
scc_hashtable_cstr_init(&linker->str2offset);
|
||||||
|
scc_vec_init(linker->symtab);
|
||||||
|
scc_vec_init(linker->relocs);
|
||||||
|
linker->entry_symbol_name = "_scc_entry";
|
||||||
|
}
|
||||||
|
|
||||||
|
void sccf_linker_add_sccf(sccf_linker_t *linker, const sccf_t *sccf) {
|
||||||
|
scc_vec_push(linker->link_sccfs, *sccf);
|
||||||
|
}
|
||||||
|
|
||||||
|
void sccf_linker_set_entry_symbol_name(sccf_linker_t *linker, const char *name) {
|
||||||
|
linker->entry_symbol_name = name ? name : "_scc_entry";
|
||||||
|
}
|
||||||
|
|
||||||
|
// Per-module extracted data (borrowed references to the original SCCF data)
|
||||||
|
typedef struct {
|
||||||
|
usize code_base; // offset of this module's code in merged_code
|
||||||
|
usize data_base; // offset of this module's data in merged_data
|
||||||
|
usize code_size;
|
||||||
|
usize data_size;
|
||||||
|
u8 *code_data;
|
||||||
|
u8 *data_data;
|
||||||
|
char *strtab_data;
|
||||||
|
usize strtab_size;
|
||||||
|
sccf_sym_t *sym_data;
|
||||||
|
usize sym_count;
|
||||||
|
sccf_reloc_t *reloc_data;
|
||||||
|
usize reloc_count;
|
||||||
|
} mod_ctx_t;
|
||||||
|
|
||||||
|
// Look up a section in an SCCF module by type, extract info
|
||||||
|
static void extract_mod_sections(sccf_t *mod, mod_ctx_t *ctx) {
|
||||||
|
scc_vec_foreach(mod->sect_headers, i) {
|
||||||
|
sccf_sect_header_t *sh = &scc_vec_at(mod->sect_headers, i);
|
||||||
|
sccf_sect_data_t *sd = &scc_vec_at(mod->sect_datas, i);
|
||||||
|
|
||||||
|
switch (sh->sccf_sect_type) {
|
||||||
|
case SCCF_SECT_CODE:
|
||||||
|
ctx->code_data = scc_vec_unsafe_get_data(*sd);
|
||||||
|
ctx->code_size = scc_vec_size(*sd);
|
||||||
|
break;
|
||||||
|
case SCCF_SECT_DATA:
|
||||||
|
ctx->data_data = scc_vec_unsafe_get_data(*sd);
|
||||||
|
ctx->data_size = scc_vec_size(*sd);
|
||||||
|
break;
|
||||||
|
case SCCF_SECT_STRTAB:
|
||||||
|
ctx->strtab_data = (char *)scc_vec_unsafe_get_data(*sd);
|
||||||
|
ctx->strtab_size = scc_vec_size(*sd);
|
||||||
|
break;
|
||||||
|
case SCCF_SECT_SYMTAB:
|
||||||
|
ctx->sym_data = (sccf_sym_t *)scc_vec_unsafe_get_data(*sd);
|
||||||
|
ctx->sym_count = scc_vec_size(*sd) / sizeof(sccf_sym_t);
|
||||||
|
break;
|
||||||
|
case SCCF_SECT_RELOCS:
|
||||||
|
ctx->reloc_data = (sccf_reloc_t *)scc_vec_unsafe_get_data(*sd);
|
||||||
|
ctx->reloc_count = scc_vec_size(*sd) / sizeof(sccf_reloc_t);
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
const sccf_t *sccf_linker_link(sccf_linker_t *linker) {
|
||||||
|
usize num_modules = scc_vec_size(linker->link_sccfs);
|
||||||
|
if (num_modules <= 1) {
|
||||||
|
return sccf_builder_to_sccf(&linker->builder);
|
||||||
|
}
|
||||||
|
|
||||||
|
sccf_builder_t *builder = &linker->builder;
|
||||||
|
|
||||||
|
// Concatenated section data
|
||||||
|
sccf_sect_data_t merged_code, merged_data;
|
||||||
|
scc_vec_init(merged_code);
|
||||||
|
scc_vec_init(merged_data);
|
||||||
|
|
||||||
|
// Per-module context
|
||||||
|
SCC_VEC(mod_ctx_t) mods;
|
||||||
|
scc_vec_init(mods);
|
||||||
|
|
||||||
|
// Phase 1: extract data from each module, concatenate code and data sections
|
||||||
|
scc_vec_foreach(linker->link_sccfs, m) {
|
||||||
|
sccf_t *mod = &scc_vec_at(linker->link_sccfs, m);
|
||||||
|
mod_ctx_t ctx = {0};
|
||||||
|
|
||||||
|
extract_mod_sections(mod, &ctx);
|
||||||
|
|
||||||
|
ctx.code_base = scc_vec_size(merged_code);
|
||||||
|
for (usize j = 0; j < ctx.code_size; j++) {
|
||||||
|
scc_vec_push(merged_code, ctx.code_data[j]);
|
||||||
|
}
|
||||||
|
|
||||||
|
ctx.data_base = scc_vec_size(merged_data);
|
||||||
|
for (usize j = 0; j < ctx.data_size; j++) {
|
||||||
|
scc_vec_push(merged_data, ctx.data_data[j]);
|
||||||
|
}
|
||||||
|
|
||||||
|
scc_vec_push(mods, ctx);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Phase 2: build unified symbol table.
|
||||||
|
// For each module, map local symbol index -> global symbol index.
|
||||||
|
// GLOBAL/EXTERN symbols are deduplicated by name.
|
||||||
|
// LOCAL symbols get unique entries per module (even if names collide).
|
||||||
|
|
||||||
|
typedef SCC_VEC(usize) idx_map_t;
|
||||||
|
SCC_VEC(idx_map_t) maps;
|
||||||
|
scc_vec_init(maps);
|
||||||
|
|
||||||
|
// First pass: collect all GLOBAL symbol definitions into the unified table
|
||||||
|
scc_vec_foreach(mods, m) {
|
||||||
|
mod_ctx_t *ctx = &scc_vec_at(mods, m);
|
||||||
|
idx_map_t map;
|
||||||
|
scc_vec_init(map);
|
||||||
|
|
||||||
|
// Index 0 = null symbol
|
||||||
|
scc_vec_push(map, 0);
|
||||||
|
|
||||||
|
for (usize j = 1; j < ctx->sym_count; j++) {
|
||||||
|
sccf_sym_t *sym = &ctx->sym_data[j];
|
||||||
|
const char *name = &ctx->strtab_data[sym->name_offset];
|
||||||
|
|
||||||
|
// Look up in unified table
|
||||||
|
usize global_idx =
|
||||||
|
(usize)scc_hashtable_get(&linker->str2offset, name);
|
||||||
|
|
||||||
|
if (global_idx == 0) {
|
||||||
|
// New symbol: add to builder's symtab/strtab
|
||||||
|
sccf_sym_t adjusted = *sym;
|
||||||
|
if (adjusted.sccf_sect_type == SCCF_SECT_CODE) {
|
||||||
|
adjusted.sccf_sect_offset += ctx->code_base;
|
||||||
|
} else if (adjusted.sccf_sect_type == SCCF_SECT_DATA) {
|
||||||
|
adjusted.sccf_sect_offset += ctx->data_base;
|
||||||
|
}
|
||||||
|
|
||||||
|
usize name_off = scc_vec_size(builder->strtab);
|
||||||
|
const char *p = name;
|
||||||
|
while (*p) {
|
||||||
|
scc_vec_push(builder->strtab, *p);
|
||||||
|
p++;
|
||||||
|
}
|
||||||
|
scc_vec_push(builder->strtab, '\0');
|
||||||
|
adjusted.name_offset = name_off;
|
||||||
|
|
||||||
|
global_idx = scc_vec_size(builder->symtab);
|
||||||
|
scc_vec_push(builder->symtab, adjusted);
|
||||||
|
scc_hashtable_set(&linker->str2offset, name,
|
||||||
|
(void *)global_idx);
|
||||||
|
|
||||||
|
} else {
|
||||||
|
// Symbol already exists in unified table.
|
||||||
|
// If the new entry is a definition and existing is UNDEF/EXTERN,
|
||||||
|
// update the existing entry with the definition.
|
||||||
|
sccf_sym_t *existing = &scc_vec_at(builder->symtab, global_idx);
|
||||||
|
bool existing_is_ref =
|
||||||
|
existing->sccf_sym_type == SCCF_SYM_TYPE_UNDEF ||
|
||||||
|
existing->sccf_sym_type == SCCF_SYM_TYPE_EXTERN;
|
||||||
|
bool new_is_def =
|
||||||
|
sym->sccf_sym_type != SCCF_SYM_TYPE_UNDEF &&
|
||||||
|
sym->sccf_sym_type != SCCF_SYM_TYPE_EXTERN;
|
||||||
|
|
||||||
|
if (new_is_def && existing_is_ref) {
|
||||||
|
sccf_sym_t adjusted = *sym;
|
||||||
|
if (adjusted.sccf_sect_type == SCCF_SECT_CODE) {
|
||||||
|
adjusted.sccf_sect_offset += ctx->code_base;
|
||||||
|
} else if (adjusted.sccf_sect_type == SCCF_SECT_DATA) {
|
||||||
|
adjusted.sccf_sect_offset += ctx->data_base;
|
||||||
|
}
|
||||||
|
adjusted.name_offset = existing->name_offset;
|
||||||
|
*existing = adjusted;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
scc_vec_push(map, global_idx);
|
||||||
|
}
|
||||||
|
scc_vec_push(maps, map);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Phase 3: process relocations.
|
||||||
|
// For each module, for each non-empty relocation:
|
||||||
|
// - Look up the target symbol in the unified table
|
||||||
|
// - If the symbol is now resolved (was EXTERN/UNDEF, now GLOBAL),
|
||||||
|
// patch the merged code in-place
|
||||||
|
// - If still unresolved, keep the relocation for DLL import resolution
|
||||||
|
|
||||||
|
// Build mcode wrapper around merged_code for patching.
|
||||||
|
// adopt_buf transfers ownership, so merged_code is emptied then refilled by
|
||||||
|
// disown_buf after patching. The cast is safe: both sccf_sect_data_t and
|
||||||
|
// scc_mcode_buff_t are SCC_VEC(u8) with identical layout.
|
||||||
|
scc_mcode_t mcode;
|
||||||
|
scc_mcode_init(&mcode, SCC_MCODE_ARCH_X86_64);
|
||||||
|
scc_mcode_adopt_buf(&mcode, (scc_mcode_buff_t *)&merged_code);
|
||||||
|
|
||||||
|
scc_vec_foreach(mods, m) {
|
||||||
|
mod_ctx_t *ctx = &scc_vec_at(mods, m);
|
||||||
|
idx_map_t *map = &scc_vec_at(maps, m);
|
||||||
|
|
||||||
|
for (usize j = 0; j < ctx->reloc_count; j++) {
|
||||||
|
sccf_reloc_t reloc = ctx->reloc_data[j];
|
||||||
|
if (reloc.reloc_type == SCCF_RELOC_TYPE_EMPTY)
|
||||||
|
continue;
|
||||||
|
|
||||||
|
Assert(reloc.sym_idx < scc_vec_size(*map));
|
||||||
|
|
||||||
|
usize global_idx = scc_vec_at(*map, reloc.sym_idx);
|
||||||
|
Assert(global_idx < scc_vec_size(builder->symtab));
|
||||||
|
sccf_sym_t *target = &scc_vec_at(builder->symtab, global_idx);
|
||||||
|
|
||||||
|
if (target->sccf_sym_type == SCCF_SYM_TYPE_EXTERN ||
|
||||||
|
target->sccf_sym_type == SCCF_SYM_TYPE_UNDEF) {
|
||||||
|
// Still unresolved: keep for DLL import resolution
|
||||||
|
reloc.sym_idx = global_idx;
|
||||||
|
sccf_builder_add_reloc(builder, reloc);
|
||||||
|
} else {
|
||||||
|
// Resolved: patch code in-place
|
||||||
|
usize patch_site = reloc.offset + reloc.addend + ctx->code_base;
|
||||||
|
usize target_off = target->sccf_sect_offset;
|
||||||
|
|
||||||
|
scc_x86_patch(&mcode, SCC_X86_PATCH_PC32, patch_site,
|
||||||
|
target_off);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Return merged data ownership from mcode back to merged_code
|
||||||
|
scc_mcode_disown_buf(&mcode, (scc_mcode_buff_t *)&merged_code);
|
||||||
|
scc_mcode_drop(&mcode);
|
||||||
|
|
||||||
|
// Phase 4: add merged sections to builder
|
||||||
|
if (scc_vec_size(merged_code) > 0) {
|
||||||
|
sccf_builder_add_text_section(builder, &merged_code);
|
||||||
|
}
|
||||||
|
if (scc_vec_size(merged_data) > 0) {
|
||||||
|
sccf_builder_add_data_section(builder, &merged_data);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Set entry point
|
||||||
|
sccf_builder_set_entry_symbol_name(builder, linker->entry_symbol_name);
|
||||||
|
|
||||||
|
// Cleanup per-module data
|
||||||
|
scc_vec_foreach(maps, i) {
|
||||||
|
scc_vec_free(scc_vec_at(maps, i));
|
||||||
|
}
|
||||||
|
scc_vec_free(maps);
|
||||||
|
// mod_ctx entries borrow references — no vec data to free for them
|
||||||
|
scc_vec_free(mods);
|
||||||
|
scc_vec_free(merged_code);
|
||||||
|
scc_vec_free(merged_data);
|
||||||
|
|
||||||
|
return sccf_builder_to_sccf(builder);
|
||||||
|
}
|
||||||
2
libs/sccf/src/sccf_log.c
Normal file
2
libs/sccf/src/sccf_log.c
Normal file
@@ -0,0 +1,2 @@
|
|||||||
|
#define __SCCF_LOG_IMPL__
|
||||||
|
#include <sccf_log.h>
|
||||||
@@ -1,10 +1,11 @@
|
|||||||
#ifndef __SCC_SSTREAM_H__
|
#ifndef __SCC_SSTREAM_H__
|
||||||
#define __SCC_SSTREAM_H__
|
#define __SCC_SSTREAM_H__
|
||||||
|
|
||||||
|
#include <scc_log.h>
|
||||||
|
|
||||||
#include <scc_core.h>
|
#include <scc_core.h>
|
||||||
#include <scc_core_ring.h>
|
#include <scc_core_ring.h>
|
||||||
#include <scc_pos.h>
|
#include <scc_pos.h>
|
||||||
#include <scc_pos_log.h>
|
|
||||||
|
|
||||||
typedef struct {
|
typedef struct {
|
||||||
scc_pos_t pos;
|
scc_pos_t pos;
|
||||||
|
|||||||
26
libs/sstream/include/scc_sstream_log.h
Normal file
26
libs/sstream/include/scc_sstream_log.h
Normal file
@@ -0,0 +1,26 @@
|
|||||||
|
#ifndef __SCC_SSTREAM_LOG_H__
|
||||||
|
#define __SCC_SSTREAM_LOG_H__
|
||||||
|
|
||||||
|
typedef struct logger logger_t;
|
||||||
|
extern logger_t __scc_sstream_log;
|
||||||
|
extern logger_t __scc_sstream_user;
|
||||||
|
|
||||||
|
#define SCC_LOG_HANDLER &__scc_sstream_user
|
||||||
|
#define LOG_DEFAULT_HANDLER &__scc_sstream_log
|
||||||
|
#include <scc_log.h>
|
||||||
|
|
||||||
|
#ifdef __SCC_SSTREAM_LOG_IMPL__
|
||||||
|
logger_t __scc_sstream_log = {
|
||||||
|
.name = "sstream",
|
||||||
|
.level = LOG_LEVEL_ALL,
|
||||||
|
.handler = log_default_handler,
|
||||||
|
};
|
||||||
|
|
||||||
|
logger_t __scc_sstream_user = {
|
||||||
|
.name = "sstream",
|
||||||
|
.level = LOG_LEVEL_ALL,
|
||||||
|
.user_handler = scc_log_handler,
|
||||||
|
};
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#endif /* __SCC_SSTREAM_LOG_H__ */
|
||||||
@@ -1,3 +1,6 @@
|
|||||||
|
#define __SCC_SSTREAM_LOG_IMPL__
|
||||||
|
#include <scc_sstream_log.h>
|
||||||
|
|
||||||
#include <scc_sstream.h>
|
#include <scc_sstream.h>
|
||||||
|
|
||||||
// 内部扫描函数:从指定位置扫描下一个有效字符
|
// 内部扫描函数:从指定位置扫描下一个有效字符
|
||||||
@@ -91,7 +94,7 @@ int scc_sstream_init(scc_sstream_t *stream, const char *fname, int ring_size) {
|
|||||||
if (fsize == 0) {
|
if (fsize == 0) {
|
||||||
stream->fill_pos = scc_pos_create();
|
stream->fill_pos = scc_pos_create();
|
||||||
stream->fill_pos.name = fname;
|
stream->fill_pos.name = fname;
|
||||||
SCC_WARN(stream->fill_pos, "file size is 0");
|
LOG_WARN("file size is 0");
|
||||||
scc_sstream_init_by_buffer(stream, "", 0, false, ring_size);
|
scc_sstream_init_by_buffer(stream, "", 0, false, ring_size);
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|||||||
26
libs/target/pe/include/scc_pe_log.h
Normal file
26
libs/target/pe/include/scc_pe_log.h
Normal file
@@ -0,0 +1,26 @@
|
|||||||
|
#ifndef __SCC_PE_LOG_H__
|
||||||
|
#define __SCC_PE_LOG_H__
|
||||||
|
|
||||||
|
typedef struct logger logger_t;
|
||||||
|
extern logger_t __scc_pe_log;
|
||||||
|
extern logger_t __scc_pe_user;
|
||||||
|
|
||||||
|
#define SCC_LOG_HANDLER &__scc_pe_user
|
||||||
|
#define LOG_DEFAULT_HANDLER &__scc_pe_log
|
||||||
|
#include <scc_log.h>
|
||||||
|
|
||||||
|
#ifdef __SCC_PE_LOG_IMPL__
|
||||||
|
logger_t __scc_pe_log = {
|
||||||
|
.name = "pe",
|
||||||
|
.level = LOG_LEVEL_ALL,
|
||||||
|
.handler = log_default_handler,
|
||||||
|
};
|
||||||
|
|
||||||
|
logger_t __scc_pe_user = {
|
||||||
|
.name = "pe",
|
||||||
|
.level = LOG_LEVEL_ALL,
|
||||||
|
.user_handler = scc_log_handler,
|
||||||
|
};
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#endif
|
||||||
@@ -1,9 +1,7 @@
|
|||||||
#include <scc_pe_builder.h>
|
#define __SCC_PE_LOG_IMPL__
|
||||||
|
#include <scc_pe_log.h>
|
||||||
|
|
||||||
#ifdef LOG_INFO
|
#include <scc_pe_builder.h>
|
||||||
#undef LOG_INFO
|
|
||||||
#endif
|
|
||||||
#define LOG_INFO(...)
|
|
||||||
|
|
||||||
#define reserve_align(offset, size) ((offset) + ((size) - 1)) & ~((size) - 1)
|
#define reserve_align(offset, size) ((offset) + ((size) - 1)) & ~((size) - 1)
|
||||||
|
|
||||||
|
|||||||
@@ -1,3 +1,5 @@
|
|||||||
|
#include <scc_pe_log.h>
|
||||||
|
|
||||||
#include <scc_pe_idata.h>
|
#include <scc_pe_idata.h>
|
||||||
|
|
||||||
// RVA Relative Virtual Address
|
// RVA Relative Virtual Address
|
||||||
|
|||||||
@@ -1,5 +1,6 @@
|
|||||||
#include <scc_pe_idata.h>
|
#include <scc_pe_idata.h>
|
||||||
#include <sccf2pe.h>
|
#include <sccf2pe.h>
|
||||||
|
#include <sccf_log.h>
|
||||||
#include <sccf_utils.h>
|
#include <sccf_utils.h>
|
||||||
#include <x86/scc_x86_patch.h>
|
#include <x86/scc_x86_patch.h>
|
||||||
|
|
||||||
|
|||||||
@@ -54,7 +54,6 @@ int log_default_handler(logger_t *module, log_level_t level, const char *file,
|
|||||||
}
|
}
|
||||||
va_end(args);
|
va_end(args);
|
||||||
log_puts(module->buf);
|
log_puts(module->buf);
|
||||||
log_puts("\n");
|
|
||||||
// for clangd warning
|
// for clangd warning
|
||||||
// clang-analyzer-deadcode.DeadStores
|
// clang-analyzer-deadcode.DeadStores
|
||||||
(void)color_code;
|
(void)color_code;
|
||||||
|
|||||||
@@ -76,7 +76,10 @@ typedef int (*log_handler)(logger_t *module, log_level_t level,
|
|||||||
struct logger {
|
struct logger {
|
||||||
const char *name; ///< 日志器名称(用于模块区分)
|
const char *name; ///< 日志器名称(用于模块区分)
|
||||||
log_level_t level; ///< 当前设置的日志级别
|
log_level_t level; ///< 当前设置的日志级别
|
||||||
log_handler handler; ///< 日志处理回调函数
|
union {
|
||||||
|
log_handler handler;
|
||||||
|
void *user_handler;
|
||||||
|
}; ///< 日志处理回调函数
|
||||||
void *user_data; ///< 用户自定义数据
|
void *user_data; ///< 用户自定义数据
|
||||||
char buf[LOGGER_MAX_BUF_SIZE]; ///< 格式化缓冲区
|
char buf[LOGGER_MAX_BUF_SIZE]; ///< 格式化缓冲区
|
||||||
};
|
};
|
||||||
@@ -84,6 +87,9 @@ struct logger {
|
|||||||
int log_default_handler(logger_t *module, log_level_t level, const char *file,
|
int log_default_handler(logger_t *module, log_level_t level, const char *file,
|
||||||
int line, const char *func, const char *fmt, ...);
|
int line, const char *func, const char *fmt, ...);
|
||||||
extern logger_t __default_logger_root;
|
extern logger_t __default_logger_root;
|
||||||
|
#ifndef LOG_DEFAULT_HANDLER
|
||||||
|
#define LOG_DEFAULT_HANDLER &__default_logger_root
|
||||||
|
#endif
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief 初始化日志实例 其余参数设置为默认值
|
* @brief 初始化日志实例 其余参数设置为默认值
|
||||||
@@ -135,13 +141,13 @@ void log_set_handler(logger_t *logger, log_handler handler);
|
|||||||
|
|
||||||
/// @name 快捷日志宏
|
/// @name 快捷日志宏
|
||||||
/// @{
|
/// @{
|
||||||
#define LOG_NOTSET(...) SCC_LOG_IMPL(&__default_logger_root, LOG_LEVEL_NOTSET, __VA_ARGS__) ///< 未分类日志
|
#define LOG_NOTSET(...) SCC_LOG_IMPL(LOG_DEFAULT_HANDLER, LOG_LEVEL_NOTSET, __VA_ARGS__) ///< 未分类日志
|
||||||
#define LOG_DEBUG(...) SCC_LOG_IMPL(&__default_logger_root, LOG_LEVEL_DEBUG, __VA_ARGS__) ///< 调试日志(需启用DEBUG级别)
|
#define LOG_DEBUG(...) SCC_LOG_IMPL(LOG_DEFAULT_HANDLER, LOG_LEVEL_DEBUG, __VA_ARGS__) ///< 调试日志(需启用DEBUG级别)
|
||||||
#define LOG_INFO(...) SCC_LOG_IMPL(&__default_logger_root, LOG_LEVEL_INFO, __VA_ARGS__) ///< 信息日志(常规运行日志)
|
#define LOG_INFO(...) SCC_LOG_IMPL(LOG_DEFAULT_HANDLER, LOG_LEVEL_INFO, __VA_ARGS__) ///< 信息日志(常规运行日志)
|
||||||
#define LOG_WARN(...) SCC_LOG_IMPL(&__default_logger_root, LOG_LEVEL_WARN, __VA_ARGS__) ///< 警告日志(潜在问题)
|
#define LOG_WARN(...) SCC_LOG_IMPL(LOG_DEFAULT_HANDLER, LOG_LEVEL_WARN, __VA_ARGS__) ///< 警告日志(潜在问题)
|
||||||
#define LOG_ERROR(...) SCC_LOG_IMPL(&__default_logger_root, LOG_LEVEL_ERROR, __VA_ARGS__) ///< 错误日志(可恢复错误)
|
#define LOG_ERROR(...) SCC_LOG_IMPL(LOG_DEFAULT_HANDLER, LOG_LEVEL_ERROR, __VA_ARGS__) ///< 错误日志(可恢复错误)
|
||||||
#define LOG_FATAL(...) SCC_LOG_IMPL(&__default_logger_root, LOG_LEVEL_FATAL, __VA_ARGS__) ///< 致命错误日志(程序终止前)
|
#define LOG_FATAL(...) SCC_LOG_IMPL(LOG_DEFAULT_HANDLER, LOG_LEVEL_FATAL, __VA_ARGS__) ///< 致命错误日志(程序终止前)
|
||||||
#define LOG_TRACE(...) SCC_LOG_IMPL(&__default_logger_root, LOG_LEVEL_TRACE, __VA_ARGS__) ///< 追踪日志(调用栈跟踪)
|
#define LOG_TRACE(...) SCC_LOG_IMPL(LOG_DEFAULT_HANDLER, LOG_LEVEL_TRACE, __VA_ARGS__) ///< 追踪日志(调用栈跟踪)
|
||||||
/// @}
|
/// @}
|
||||||
/* clang-format on */
|
/* clang-format on */
|
||||||
|
|
||||||
|
|||||||
@@ -6,7 +6,7 @@
|
|||||||
#endif
|
#endif
|
||||||
|
|
||||||
#ifndef log_puts
|
#ifndef log_puts
|
||||||
#define log_puts(str) scc_printf("%s", str)
|
#define log_puts(str) scc_printf("%s\n", str)
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#ifndef log_abort
|
#ifndef log_abort
|
||||||
|
|||||||
35
runtime/scc_core/include/scc_log.h
Normal file
35
runtime/scc_core/include/scc_log.h
Normal file
@@ -0,0 +1,35 @@
|
|||||||
|
#ifndef __SCC_POS_LOG_H__
|
||||||
|
#define __SCC_POS_LOG_H__
|
||||||
|
|
||||||
|
#include "scc_pos.h"
|
||||||
|
#include <scc_core.h>
|
||||||
|
|
||||||
|
int scc_log_handler(logger_t *module, log_level_t level, const char *file,
|
||||||
|
int line, int col, const char *fmt, ...);
|
||||||
|
typedef int (*scc_log_fn_t)(logger_t *module, log_level_t level,
|
||||||
|
const char *file, int line, int col,
|
||||||
|
const char *fmt, ...);
|
||||||
|
extern logger_t __scc_pos_log;
|
||||||
|
|
||||||
|
#define SCC_POS_LOG(logger, level, pos, fmt, ...) \
|
||||||
|
do { \
|
||||||
|
((scc_log_fn_t)(logger)->user_handler)( \
|
||||||
|
(logger), (level), scc_pos_pnt_val(pos), (fmt), ##__VA_ARGS__); \
|
||||||
|
} while (0)
|
||||||
|
|
||||||
|
#ifndef SCC_LOG_HANDLER
|
||||||
|
#define SCC_LOG_HANDLER &__scc_pos_log
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#define SCC_DEBUG(pos, fmt, ...) \
|
||||||
|
SCC_POS_LOG(SCC_LOG_HANDLER, LOG_LEVEL_DEBUG, pos, fmt, ##__VA_ARGS__)
|
||||||
|
#define SCC_INFO(pos, fmt, ...) \
|
||||||
|
SCC_POS_LOG(SCC_LOG_HANDLER, LOG_LEVEL_INFO, pos, fmt, ##__VA_ARGS__)
|
||||||
|
#define SCC_WARN(pos, fmt, ...) \
|
||||||
|
SCC_POS_LOG(SCC_LOG_HANDLER, LOG_LEVEL_WARN, pos, fmt, ##__VA_ARGS__)
|
||||||
|
#define SCC_ERROR(pos, fmt, ...) \
|
||||||
|
SCC_POS_LOG(SCC_LOG_HANDLER, LOG_LEVEL_ERROR, pos, fmt, ##__VA_ARGS__)
|
||||||
|
#define SCC_FATAL(pos, fmt, ...) \
|
||||||
|
SCC_POS_LOG(SCC_LOG_HANDLER, LOG_LEVEL_FATAL, pos, fmt, ##__VA_ARGS__)
|
||||||
|
|
||||||
|
#endif /* __SCC_POS_LOG_H__ */
|
||||||
@@ -1,21 +1,17 @@
|
|||||||
#include <scc_pos_log.h>
|
#include <scc_log.h>
|
||||||
|
|
||||||
static int pos_log_handler(logger_t *module, log_level_t level,
|
|
||||||
const char *file, int line, const char *func,
|
|
||||||
const char *fmt, ...) {
|
|
||||||
|
|
||||||
|
int scc_log_handler(logger_t *module, log_level_t level, const char *file,
|
||||||
|
int line, int col, const char *fmt, ...) {
|
||||||
/* clang-format off */
|
/* clang-format off */
|
||||||
(void) module, (void)file, (void)line, (void)func; // 不再使用
|
|
||||||
|
|
||||||
const char *level_str = nullptr;
|
const char *level_str = nullptr;
|
||||||
switch (level) {
|
switch (level) {
|
||||||
case LOG_LEVEL_DEBUG: level_str = "DEBUG"; break;
|
case LOG_LEVEL_DEBUG: level_str = "debug"; break;
|
||||||
case LOG_LEVEL_INFO: level_str = "INFO "; break;
|
case LOG_LEVEL_INFO: level_str = "info "; break;
|
||||||
case LOG_LEVEL_WARN: level_str = "WARN "; break;
|
case LOG_LEVEL_WARN: level_str = "warn "; break;
|
||||||
case LOG_LEVEL_ERROR: level_str = "ERROR"; break;
|
case LOG_LEVEL_ERROR: level_str = "error"; break;
|
||||||
case LOG_LEVEL_FATAL: level_str = "FATAL"; break;
|
case LOG_LEVEL_FATAL: level_str = "fatal"; break;
|
||||||
case LOG_LEVEL_TRACE: level_str = "TRACE"; break;
|
case LOG_LEVEL_TRACE: level_str = "trace"; break;
|
||||||
default: level_str = "NOTSET"; break;
|
default: level_str = "notset"; break;
|
||||||
}
|
}
|
||||||
/// @note: 定义 __LOG_NO_COLOR__ 会取消颜色输出
|
/// @note: 定义 __LOG_NO_COLOR__ 会取消颜色输出
|
||||||
#ifndef __LOG_NO_COLOR__
|
#ifndef __LOG_NO_COLOR__
|
||||||
@@ -32,18 +28,19 @@ static int pos_log_handler(logger_t *module, log_level_t level,
|
|||||||
#endif
|
#endif
|
||||||
/* clang-format on */
|
/* clang-format on */
|
||||||
char buf[LOGGER_MAX_BUF_SIZE];
|
char buf[LOGGER_MAX_BUF_SIZE];
|
||||||
int off = scc_snprintf(buf, sizeof(buf), "%s[%s]%s ",
|
|
||||||
color_code ? color_code : "", level_str,
|
int offset =
|
||||||
color_code ? ANSI_NONE : "");
|
scc_snprintf(module->buf, sizeof(module->buf), "%s[%s] %s - %s:%d:%d%s",
|
||||||
|
color_code ? color_code : "", level_str, module->name,
|
||||||
|
file, line, col, color_code ? ANSI_NONE : "");
|
||||||
|
|
||||||
va_list args;
|
va_list args;
|
||||||
va_start(args, fmt);
|
va_start(args, fmt);
|
||||||
scc_vsnprintf(buf + off, sizeof(buf) - off, fmt, args);
|
scc_vsnprintf(module->buf + offset, sizeof(module->buf) - offset, fmt,
|
||||||
|
args);
|
||||||
va_end(args);
|
va_end(args);
|
||||||
|
|
||||||
log_puts(buf);
|
log_puts(buf);
|
||||||
log_puts("\n");
|
|
||||||
|
|
||||||
if (level == LOG_LEVEL_FATAL) {
|
if (level == LOG_LEVEL_FATAL) {
|
||||||
log_abort();
|
log_abort();
|
||||||
}
|
}
|
||||||
@@ -52,6 +49,6 @@ static int pos_log_handler(logger_t *module, log_level_t level,
|
|||||||
|
|
||||||
logger_t __scc_pos_log = {
|
logger_t __scc_pos_log = {
|
||||||
.name = "pos_log",
|
.name = "pos_log",
|
||||||
.handler = pos_log_handler,
|
.user_handler = scc_log_handler,
|
||||||
.level = LOG_LEVEL_ALL,
|
.level = LOG_LEVEL_ALL,
|
||||||
};
|
};
|
||||||
@@ -1,31 +0,0 @@
|
|||||||
#ifndef __SCC_POS_LOG_H__
|
|
||||||
#define __SCC_POS_LOG_H__
|
|
||||||
|
|
||||||
#include "scc_pos.h"
|
|
||||||
#include <scc_core.h>
|
|
||||||
|
|
||||||
extern logger_t __scc_pos_log;
|
|
||||||
|
|
||||||
#define SCC_POS_LOG(level, pos, fmt, ...) \
|
|
||||||
do { \
|
|
||||||
char _full_msg[LOGGER_MAX_BUF_SIZE]; \
|
|
||||||
int _n = scc_snprintf(_full_msg, sizeof(_full_msg), \
|
|
||||||
scc_pos_pnt_fmt ": ", scc_pos_pnt_val(pos)); \
|
|
||||||
scc_snprintf(_full_msg + _n, sizeof(_full_msg) - _n, fmt, \
|
|
||||||
##__VA_ARGS__); \
|
|
||||||
__scc_pos_log.handler(&__scc_pos_log, level, nullptr, 0, nullptr, \
|
|
||||||
"%s", _full_msg); \
|
|
||||||
} while (0)
|
|
||||||
|
|
||||||
#define SCC_DEBUG(pos, fmt, ...) \
|
|
||||||
SCC_POS_LOG(LOG_LEVEL_DEBUG, pos, fmt, ##__VA_ARGS__)
|
|
||||||
#define SCC_INFO(pos, fmt, ...) \
|
|
||||||
SCC_POS_LOG(LOG_LEVEL_INFO, pos, fmt, ##__VA_ARGS__)
|
|
||||||
#define SCC_WARN(pos, fmt, ...) \
|
|
||||||
SCC_POS_LOG(LOG_LEVEL_WARN, pos, fmt, ##__VA_ARGS__)
|
|
||||||
#define SCC_ERROR(pos, fmt, ...) \
|
|
||||||
SCC_POS_LOG(LOG_LEVEL_ERROR, pos, fmt, ##__VA_ARGS__)
|
|
||||||
#define SCC_FATAL(pos, fmt, ...) \
|
|
||||||
SCC_POS_LOG(LOG_LEVEL_FATAL, pos, fmt, ##__VA_ARGS__)
|
|
||||||
|
|
||||||
#endif /* __SCC_POS_LOG_H__ */
|
|
||||||
@@ -45,7 +45,8 @@ void scc_hashtable_usize_init(scc_hashtable_t *ht) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
static usize next_power_of_two(usize n) {
|
static usize next_power_of_two(usize n) {
|
||||||
if (n == 0) return 32;
|
if (n == 0)
|
||||||
|
return 32;
|
||||||
n--;
|
n--;
|
||||||
n |= n >> 1;
|
n |= n >> 1;
|
||||||
n |= n >> 2;
|
n |= n >> 2;
|
||||||
@@ -56,8 +57,8 @@ static usize next_power_of_two(usize n) {
|
|||||||
return n + 1;
|
return n + 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
static scc_hashtable_entry_t *find_entry(scc_hashtable_t *ht, const void *key,
|
static scc_hashtable_entry_t *find_entry(const scc_hashtable_t *ht,
|
||||||
u32 hash) {
|
const void *key, u32 hash) {
|
||||||
if (ht->entries.cap == 0)
|
if (ht->entries.cap == 0)
|
||||||
return nullptr;
|
return nullptr;
|
||||||
|
|
||||||
|
|||||||
@@ -1,5 +1,7 @@
|
|||||||
#include <sccf_utils.h>
|
#include <sccf_log.h>
|
||||||
|
|
||||||
#include <argparse.h>
|
#include <argparse.h>
|
||||||
|
#include <sccf_utils.h>
|
||||||
|
|
||||||
void init_platform(void);
|
void init_platform(void);
|
||||||
|
|
||||||
@@ -20,67 +22,96 @@ typedef struct {
|
|||||||
|
|
||||||
static const char *arch_name(sccf_enum_t arch) {
|
static const char *arch_name(sccf_enum_t arch) {
|
||||||
switch (arch) {
|
switch (arch) {
|
||||||
case SCCF_ARCH_UNKNOWN: return "UNKNOWN";
|
case SCCF_ARCH_UNKNOWN:
|
||||||
case SCCF_ARCH_RISCV32: return "RISC-V 32";
|
return "UNKNOWN";
|
||||||
case SCCF_ARCH_RISCV64: return "RISC-V 64";
|
case SCCF_ARCH_RISCV32:
|
||||||
case SCCF_ARCH_X86: return "x86";
|
return "RISC-V 32";
|
||||||
case SCCF_ARCH_AMD64: return "AMD64";
|
case SCCF_ARCH_RISCV64:
|
||||||
default: return "UNKNOWN";
|
return "RISC-V 64";
|
||||||
|
case SCCF_ARCH_X86:
|
||||||
|
return "x86";
|
||||||
|
case SCCF_ARCH_AMD64:
|
||||||
|
return "AMD64";
|
||||||
|
default:
|
||||||
|
return "UNKNOWN";
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static const char *type_name(sccf_enum_t type) {
|
static const char *type_name(sccf_enum_t type) {
|
||||||
switch (type) {
|
switch (type) {
|
||||||
case SCCF_TYPE_FLAG_EXECUTABLE: return "executable";
|
case SCCF_TYPE_FLAG_EXECUTABLE:
|
||||||
case SCCF_TYPE_FLAG_RELOCATABLE: return "relocatable";
|
return "executable";
|
||||||
case SCCF_TYPE_FLAG_EXE_RELOC: return "exe+reloc";
|
case SCCF_TYPE_FLAG_RELOCATABLE:
|
||||||
default: return "UNKNOWN";
|
return "relocatable";
|
||||||
|
case SCCF_TYPE_FLAG_EXE_RELOC:
|
||||||
|
return "exe+reloc";
|
||||||
|
default:
|
||||||
|
return "UNKNOWN";
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static const char *sect_type_name(sccf_enum_t t) {
|
static const char *sect_type_name(sccf_enum_t t) {
|
||||||
switch (t) {
|
switch (t) {
|
||||||
case SCCF_SECT_NONE: return "NONE";
|
case SCCF_SECT_NONE:
|
||||||
case SCCF_SECT_CODE: return "CODE";
|
return "NONE";
|
||||||
case SCCF_SECT_DATA: return "DATA";
|
case SCCF_SECT_CODE:
|
||||||
case SCCF_SECT_RODATA: return "RODATA";
|
return "CODE";
|
||||||
case SCCF_SECT_UNINIT_DATA: return "BSS";
|
case SCCF_SECT_DATA:
|
||||||
case SCCF_SECT_SYMTAB: return "SYMTAB";
|
return "DATA";
|
||||||
case SCCF_SECT_STRTAB: return "STRTAB";
|
case SCCF_SECT_RODATA:
|
||||||
case SCCF_SECT_RELOCS: return "RELOCS";
|
return "RODATA";
|
||||||
default: return "UNKNOWN";
|
case SCCF_SECT_UNINIT_DATA:
|
||||||
|
return "BSS";
|
||||||
|
case SCCF_SECT_SYMTAB:
|
||||||
|
return "SYMTAB";
|
||||||
|
case SCCF_SECT_STRTAB:
|
||||||
|
return "STRTAB";
|
||||||
|
case SCCF_SECT_RELOCS:
|
||||||
|
return "RELOCS";
|
||||||
|
default:
|
||||||
|
return "UNKNOWN";
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static const char *sym_type_name(sccf_enum_t t) {
|
static const char *sym_type_name(sccf_enum_t t) {
|
||||||
switch (t) {
|
switch (t) {
|
||||||
case SCCF_SYM_TYPE_UNDEF: return "UNDEF";
|
case SCCF_SYM_TYPE_UNDEF:
|
||||||
case SCCF_SYM_TYPE_FUNC: return "FUNC";
|
return "UNDEF";
|
||||||
case SCCF_SYM_TYPE_DATA: return "DATA";
|
case SCCF_SYM_TYPE_FUNC:
|
||||||
case SCCF_SYM_TYPE_EXTERN: return "EXTERN";
|
return "FUNC";
|
||||||
default: return "?";
|
case SCCF_SYM_TYPE_DATA:
|
||||||
|
return "DATA";
|
||||||
|
case SCCF_SYM_TYPE_EXTERN:
|
||||||
|
return "EXTERN";
|
||||||
|
default:
|
||||||
|
return "?";
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static const char *sym_bind_name(sccf_enum_t b) {
|
static const char *sym_bind_name(sccf_enum_t b) {
|
||||||
switch (b) {
|
switch (b) {
|
||||||
case SCCF_SYM_BIND_LOCAL: return "LOCAL";
|
case SCCF_SYM_BIND_LOCAL:
|
||||||
case SCCF_SYM_BIND_GLOBAL: return "GLOBAL";
|
return "LOCAL";
|
||||||
case SCCF_SYM_BIND_WEAK: return "WEAK";
|
case SCCF_SYM_BIND_GLOBAL:
|
||||||
default: return "?";
|
return "GLOBAL";
|
||||||
|
case SCCF_SYM_BIND_WEAK:
|
||||||
|
return "WEAK";
|
||||||
|
default:
|
||||||
|
return "?";
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static void dump_header(const sccf_header_t *hdr) {
|
static void dump_header(const sccf_header_t *hdr) {
|
||||||
scc_printf("header:\n");
|
scc_printf("header:\n");
|
||||||
scc_printf(" magic: %c%c%c%c%c%c%c%c\n",
|
scc_printf(" magic: %c%c%c%c%c%c%c%c\n", hdr->magic[0], hdr->magic[1],
|
||||||
hdr->magic[0], hdr->magic[1], hdr->magic[2], hdr->magic[3],
|
hdr->magic[2], hdr->magic[3], hdr->magic[4], hdr->magic[5],
|
||||||
hdr->magic[4], hdr->magic[5], hdr->magic[6], hdr->magic[7]);
|
hdr->magic[6], hdr->magic[7]);
|
||||||
scc_printf(" type: %u (%s)\n", hdr->type, type_name(hdr->type));
|
scc_printf(" type: %u (%s)\n", hdr->type, type_name(hdr->type));
|
||||||
scc_printf(" version: %u\n", hdr->version);
|
scc_printf(" version: %u\n", hdr->version);
|
||||||
scc_printf(" arch: %u (%s)\n", hdr->arch, arch_name(hdr->arch));
|
scc_printf(" arch: %u (%s)\n", hdr->arch, arch_name(hdr->arch));
|
||||||
scc_printf(" entry: 0x%llx\n", (unsigned long long)hdr->entry_point);
|
scc_printf(" entry: 0x%llx\n", (unsigned long long)hdr->entry_point);
|
||||||
scc_printf(" sect_count: %llu\n", (unsigned long long)hdr->sect_header_num);
|
scc_printf(" sect_count: %llu\n",
|
||||||
|
(unsigned long long)hdr->sect_header_num);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void dump_sections(u8 *base) {
|
static void dump_sections(u8 *base) {
|
||||||
@@ -88,14 +119,14 @@ static void dump_sections(u8 *base) {
|
|||||||
scc_printf("sections:\n");
|
scc_printf("sections:\n");
|
||||||
for (usize i = 0; i < (usize)hdr->sect_header_num; i++) {
|
for (usize i = 0; i < (usize)hdr->sect_header_num; i++) {
|
||||||
const sccf_sect_header_t *sh = sccf_sect_header(base, i);
|
const sccf_sect_header_t *sh = sccf_sect_header(base, i);
|
||||||
if (!sh) break;
|
if (!sh)
|
||||||
scc_printf(" [%-2llu] %-8s size=%-8llu data_sz=%-8llu align=%-8llu name=%.8s\n",
|
break;
|
||||||
(unsigned long long)i,
|
scc_printf(" [%-2llu] %-8s size=%-8llu data_sz=%-8llu align=%-8llu "
|
||||||
sect_type_name(sh->sccf_sect_type),
|
"name=%.8s\n",
|
||||||
|
(unsigned long long)i, sect_type_name(sh->sccf_sect_type),
|
||||||
(unsigned long long)sh->size,
|
(unsigned long long)sh->size,
|
||||||
(unsigned long long)sh->data_size,
|
(unsigned long long)sh->data_size,
|
||||||
(unsigned long long)sh->addralign,
|
(unsigned long long)sh->addralign, sh->name);
|
||||||
sh->name);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -106,7 +137,7 @@ static void dump_symbols(u8 *base) {
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
usize str_idx = sccf_find_sect_by_type(base, SCCF_SECT_STRTAB);
|
usize str_idx = sccf_find_sect_by_type(base, SCCF_SECT_STRTAB);
|
||||||
const char *strtab = NULL;
|
const char *strtab = nullptr;
|
||||||
if (str_idx < ((const sccf_header_t *)base)->sect_header_num) {
|
if (str_idx < ((const sccf_header_t *)base)->sect_header_num) {
|
||||||
strtab = (const char *)sccf_sect_data(base, str_idx);
|
strtab = (const char *)sccf_sect_data(base, str_idx);
|
||||||
}
|
}
|
||||||
@@ -119,12 +150,10 @@ static void dump_symbols(u8 *base) {
|
|||||||
for (usize i = 0; i < count; i++) {
|
for (usize i = 0; i < count; i++) {
|
||||||
const char *name = strtab ? strtab + syms[i].name_offset : "";
|
const char *name = strtab ? strtab + syms[i].name_offset : "";
|
||||||
scc_printf(" [%-2llu] %-8s %-6s %-8s 0x%-6llx %s\n",
|
scc_printf(" [%-2llu] %-8s %-6s %-8s 0x%-6llx %s\n",
|
||||||
(unsigned long long)i,
|
(unsigned long long)i, sym_type_name(syms[i].sccf_sym_type),
|
||||||
sym_type_name(syms[i].sccf_sym_type),
|
|
||||||
sym_bind_name(syms[i].sccf_sym_bind),
|
sym_bind_name(syms[i].sccf_sym_bind),
|
||||||
sect_type_name(syms[i].sccf_sect_type),
|
sect_type_name(syms[i].sccf_sect_type),
|
||||||
(unsigned long long)syms[i].sccf_sect_offset,
|
(unsigned long long)syms[i].sccf_sect_offset, name);
|
||||||
name);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -137,13 +166,14 @@ static void dump_relocs(u8 *base) {
|
|||||||
|
|
||||||
const sccf_sect_header_t *sh = sccf_sect_header(base, reloc_idx);
|
const sccf_sect_header_t *sh = sccf_sect_header(base, reloc_idx);
|
||||||
usize count = sh->size / sizeof(sccf_reloc_t);
|
usize count = sh->size / sizeof(sccf_reloc_t);
|
||||||
const sccf_reloc_t *relocs = (const sccf_reloc_t *)sccf_sect_data(base, reloc_idx);
|
const sccf_reloc_t *relocs =
|
||||||
|
(const sccf_reloc_t *)sccf_sect_data(base, reloc_idx);
|
||||||
|
|
||||||
scc_printf("relocations:\n");
|
scc_printf("relocations:\n");
|
||||||
for (usize i = 0; i < count; i++) {
|
for (usize i = 0; i < count; i++) {
|
||||||
scc_printf(" [%-2llu] type=%-3u sect=%-8s sym=%-2llu offset=0x%-6llx\n",
|
scc_printf(
|
||||||
(unsigned long long)i,
|
" [%-2llu] type=%-3u sect=%-8s sym=%-2llu offset=0x%-6llx\n",
|
||||||
relocs[i].reloc_type,
|
(unsigned long long)i, relocs[i].reloc_type,
|
||||||
sect_type_name(relocs[i].sect_type),
|
sect_type_name(relocs[i].sect_type),
|
||||||
(unsigned long long)relocs[i].sym_idx,
|
(unsigned long long)relocs[i].sym_idx,
|
||||||
(unsigned long long)relocs[i].offset);
|
(unsigned long long)relocs[i].offset);
|
||||||
@@ -160,15 +190,19 @@ static void dump_hex(u8 *base, int verbose) {
|
|||||||
continue;
|
continue;
|
||||||
|
|
||||||
u8 *data = sccf_sect_data(base, i);
|
u8 *data = sccf_sect_data(base, i);
|
||||||
if (!data || sh->size == 0) continue;
|
if (!data || sh->size == 0)
|
||||||
|
continue;
|
||||||
|
|
||||||
scc_printf("section [%-2llu] %.8s (%llu bytes):\n",
|
scc_printf("section [%-2llu] %.8s (%llu bytes):\n",
|
||||||
(unsigned long long)i, sh->name, (unsigned long long)sh->size);
|
(unsigned long long)i, sh->name,
|
||||||
|
(unsigned long long)sh->size);
|
||||||
usize limit = verbose ? sh->size : (sh->size > 256 ? 256 : sh->size);
|
usize limit = verbose ? sh->size : (sh->size > 256 ? 256 : sh->size);
|
||||||
for (usize j = 0; j < limit; j++) {
|
for (usize j = 0; j < limit; j++) {
|
||||||
if (j % 16 == 0) scc_printf(" %08llx: ", (unsigned long long)j);
|
if (j % 16 == 0)
|
||||||
|
scc_printf(" %08llx: ", (unsigned long long)j);
|
||||||
scc_printf("%02x ", data[j]);
|
scc_printf("%02x ", data[j]);
|
||||||
if ((j + 1) % 16 == 0 || j + 1 == limit) scc_printf("\n");
|
if ((j + 1) % 16 == 0 || j + 1 == limit)
|
||||||
|
scc_printf("\n");
|
||||||
}
|
}
|
||||||
if (limit < sh->size)
|
if (limit < sh->size)
|
||||||
scc_printf(" ... (%llu more bytes)\n",
|
scc_printf(" ... (%llu more bytes)\n",
|
||||||
@@ -240,7 +274,8 @@ int main(int argc, const char **argv, const char **envp) {
|
|||||||
config.get_section_idx = -1;
|
config.get_section_idx = -1;
|
||||||
|
|
||||||
scc_argparse_t argparse;
|
scc_argparse_t argparse;
|
||||||
scc_argparse_init(&argparse, hints[HINT_PROG_NAME], hints[HINT_DESCRIPTION]);
|
scc_argparse_init(&argparse, hints[HINT_PROG_NAME],
|
||||||
|
hints[HINT_DESCRIPTION]);
|
||||||
argparse.lang = lang;
|
argparse.lang = lang;
|
||||||
|
|
||||||
scc_argparse_cmd_t *root = scc_argparse_get_root(&argparse);
|
scc_argparse_cmd_t *root = scc_argparse_get_root(&argparse);
|
||||||
@@ -286,13 +321,17 @@ int main(int argc, const char **argv, const char **envp) {
|
|||||||
scc_argparse_cmd_add_opt(root, &opt_verbose);
|
scc_argparse_cmd_add_opt(root, &opt_verbose);
|
||||||
|
|
||||||
scc_argparse_opt_t opt_get_section;
|
scc_argparse_opt_t opt_get_section;
|
||||||
scc_argparse_opt_init(&opt_get_section, 0, "get-section", hints[HINT_GET_SECTION]);
|
scc_argparse_opt_init(&opt_get_section, 0, "get-section",
|
||||||
scc_argparse_spec_setup_string(&opt_get_section.spec, &config.get_section_name);
|
hints[HINT_GET_SECTION]);
|
||||||
|
scc_argparse_spec_setup_string(&opt_get_section.spec,
|
||||||
|
&config.get_section_name);
|
||||||
scc_argparse_cmd_add_opt(root, &opt_get_section);
|
scc_argparse_cmd_add_opt(root, &opt_get_section);
|
||||||
|
|
||||||
scc_argparse_opt_t opt_get_section_idx;
|
scc_argparse_opt_t opt_get_section_idx;
|
||||||
scc_argparse_opt_init(&opt_get_section_idx, 0, "get-section-idx", hints[HINT_GET_SECTION_IDX]);
|
scc_argparse_opt_init(&opt_get_section_idx, 0, "get-section-idx",
|
||||||
scc_argparse_spec_setup_int(&opt_get_section_idx.spec, &config.get_section_idx);
|
hints[HINT_GET_SECTION_IDX]);
|
||||||
|
scc_argparse_spec_setup_int(&opt_get_section_idx.spec,
|
||||||
|
&config.get_section_idx);
|
||||||
scc_argparse_cmd_add_opt(root, &opt_get_section_idx);
|
scc_argparse_cmd_add_opt(root, &opt_get_section_idx);
|
||||||
|
|
||||||
scc_argparse_arg_t arg_file;
|
scc_argparse_arg_t arg_file;
|
||||||
@@ -310,14 +349,14 @@ int main(int argc, const char **argv, const char **envp) {
|
|||||||
|
|
||||||
scc_file_t fp = scc_fopen(config.filepath, SCC_FILE_READ);
|
scc_file_t fp = scc_fopen(config.filepath, SCC_FILE_READ);
|
||||||
if (!fp) {
|
if (!fp) {
|
||||||
LOG_ERROR("cannot open %s", config.filepath);
|
SCC_ERROR((scc_pos_t){0}, "cannot open %s", config.filepath);
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
usize fsize = scc_fsize(fp);
|
usize fsize = scc_fsize(fp);
|
||||||
if (fsize < sizeof(sccf_header_t)) {
|
if (fsize < sizeof(sccf_header_t)) {
|
||||||
LOG_ERROR("file too small: %s (%llu bytes)", config.filepath,
|
SCC_ERROR((scc_pos_t){0}, "file too small: %s (%llu bytes)",
|
||||||
(unsigned long long)fsize);
|
config.filepath, (unsigned long long)fsize);
|
||||||
scc_fclose(fp);
|
scc_fclose(fp);
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
@@ -328,7 +367,7 @@ int main(int argc, const char **argv, const char **envp) {
|
|||||||
usize nread = scc_fread(fp, scc_vec_unsafe_get_data(buf), fsize);
|
usize nread = scc_fread(fp, scc_vec_unsafe_get_data(buf), fsize);
|
||||||
scc_fclose(fp);
|
scc_fclose(fp);
|
||||||
if (nread != fsize) {
|
if (nread != fsize) {
|
||||||
LOG_ERROR("short read %s", config.filepath);
|
SCC_ERROR((scc_pos_t){0}, "short read %s", config.filepath);
|
||||||
scc_vec_free(buf);
|
scc_vec_free(buf);
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
@@ -347,14 +386,15 @@ int main(int argc, const char **argv, const char **envp) {
|
|||||||
const sccf_header_t *hdr = (const sccf_header_t *)base;
|
const sccf_header_t *hdr = (const sccf_header_t *)base;
|
||||||
for (usize i = 0; i < (usize)hdr->sect_header_num; i++) {
|
for (usize i = 0; i < (usize)hdr->sect_header_num; i++) {
|
||||||
const sccf_sect_header_t *sh = sccf_sect_header(base, i);
|
const sccf_sect_header_t *sh = sccf_sect_header(base, i);
|
||||||
if (sh && scc_memcmp(sh->name,
|
if (sh &&
|
||||||
config.get_section_name, 8) == 0) {
|
scc_memcmp(sh->name, config.get_section_name, 8) == 0) {
|
||||||
idx = i;
|
idx = i;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (idx == (usize)-1) {
|
if (idx == (usize)-1) {
|
||||||
LOG_ERROR("section not found: %s", config.get_section_name);
|
SCC_ERROR((scc_pos_t){0}, "section not found: %s",
|
||||||
|
config.get_section_name);
|
||||||
scc_vec_free(buf);
|
scc_vec_free(buf);
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
@@ -362,7 +402,8 @@ int main(int argc, const char **argv, const char **envp) {
|
|||||||
|
|
||||||
const sccf_sect_header_t *sh = sccf_sect_header(base, idx);
|
const sccf_sect_header_t *sh = sccf_sect_header(base, idx);
|
||||||
if (!sh) {
|
if (!sh) {
|
||||||
LOG_ERROR("invalid section index: %d", config.get_section_idx);
|
SCC_ERROR((scc_pos_t){0}, "invalid section index: %d",
|
||||||
|
config.get_section_idx);
|
||||||
scc_vec_free(buf);
|
scc_vec_free(buf);
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
@@ -377,7 +418,8 @@ int main(int argc, const char **argv, const char **envp) {
|
|||||||
} else if (config.output) {
|
} else if (config.output) {
|
||||||
scc_file_t ofp = scc_fopen(config.output, SCC_FILE_WRITE);
|
scc_file_t ofp = scc_fopen(config.output, SCC_FILE_WRITE);
|
||||||
if (!ofp) {
|
if (!ofp) {
|
||||||
LOG_ERROR("cannot open output: %s", config.output);
|
SCC_ERROR((scc_pos_t){0}, "cannot open output: %s",
|
||||||
|
config.output);
|
||||||
scc_vec_free(buf);
|
scc_vec_free(buf);
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
@@ -398,12 +440,17 @@ int main(int argc, const char **argv, const char **envp) {
|
|||||||
dump_symbols(base);
|
dump_symbols(base);
|
||||||
dump_relocs(base);
|
dump_relocs(base);
|
||||||
} else {
|
} else {
|
||||||
if (config.dump_header) dump_header(&sccf.header);
|
if (config.dump_header)
|
||||||
if (config.dump_sections) dump_sections(base);
|
dump_header(&sccf.header);
|
||||||
if (config.dump_symbols) dump_symbols(base);
|
if (config.dump_sections)
|
||||||
if (config.dump_relocs) dump_relocs(base);
|
dump_sections(base);
|
||||||
|
if (config.dump_symbols)
|
||||||
|
dump_symbols(base);
|
||||||
|
if (config.dump_relocs)
|
||||||
|
dump_relocs(base);
|
||||||
}
|
}
|
||||||
if (config.dump_hex) dump_hex(base, config.verbose);
|
if (config.dump_hex)
|
||||||
|
dump_hex(base, config.verbose);
|
||||||
|
|
||||||
scc_vec_free(buf);
|
scc_vec_free(buf);
|
||||||
return 0;
|
return 0;
|
||||||
|
|||||||
25
src/cmd_log.h
Normal file
25
src/cmd_log.h
Normal file
@@ -0,0 +1,25 @@
|
|||||||
|
#ifndef __SCC_CMD_LOG_H__
|
||||||
|
#define __SCC_CMD_LOG_H__
|
||||||
|
typedef struct logger logger_t;
|
||||||
|
extern logger_t __scc_cmd_log;
|
||||||
|
extern logger_t __scc_cmd_user;
|
||||||
|
|
||||||
|
#define SCC_LOG_HANDLER &__scc_cmd_user
|
||||||
|
#define LOG_DEFAULT_HANDLER &__scc_cmd_log
|
||||||
|
#include <scc_log.h>
|
||||||
|
|
||||||
|
#ifdef __SCC_CMD_LOG_IMPL__
|
||||||
|
logger_t __scc_cmd_log = {
|
||||||
|
.name = "scc",
|
||||||
|
.level = LOG_LEVEL_ALL,
|
||||||
|
.handler = log_default_handler,
|
||||||
|
};
|
||||||
|
|
||||||
|
logger_t __scc_cmd_user = {
|
||||||
|
.name = "scc",
|
||||||
|
.level = LOG_LEVEL_ALL,
|
||||||
|
.user_handler = scc_log_handler,
|
||||||
|
};
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#endif
|
||||||
14
src/config.c
14
src/config.c
@@ -9,6 +9,7 @@ void setup_argparse(scc_argparse_t *argparse, scc_config_t *config,
|
|||||||
SCC_HINT_INPUT_FILE,
|
SCC_HINT_INPUT_FILE,
|
||||||
SCC_HINT_INCLUDE_PATH,
|
SCC_HINT_INCLUDE_PATH,
|
||||||
SCC_HINT_DEFINED_MACRO,
|
SCC_HINT_DEFINED_MACRO,
|
||||||
|
SCC_HINT_LOG_CONFIG,
|
||||||
SCC_HINT_TARGET_DESC,
|
SCC_HINT_TARGET_DESC,
|
||||||
SCC_HINT_VERBOSE,
|
SCC_HINT_VERBOSE,
|
||||||
|
|
||||||
@@ -35,6 +36,7 @@ void setup_argparse(scc_argparse_t *argparse, scc_config_t *config,
|
|||||||
[SCC_HINT_INPUT_FILE] = "Input source file",
|
[SCC_HINT_INPUT_FILE] = "Input source file",
|
||||||
[SCC_HINT_INCLUDE_PATH] = "Add directory to the include search paths",
|
[SCC_HINT_INCLUDE_PATH] = "Add directory to the include search paths",
|
||||||
[SCC_HINT_DEFINED_MACRO] = "Define a macro",
|
[SCC_HINT_DEFINED_MACRO] = "Define a macro",
|
||||||
|
[SCC_HINT_LOG_CONFIG] = "Set per-module log level (eg. --log pproc=debug)",
|
||||||
[SCC_HINT_TARGET_DESC] =
|
[SCC_HINT_TARGET_DESC] =
|
||||||
"Target description(eg. x86_64-pc-windows-msvc)",
|
"Target description(eg. x86_64-pc-windows-msvc)",
|
||||||
[SCC_HINT_VERBOSE] = "Increase verbosity (can be used multiple times)",
|
[SCC_HINT_VERBOSE] = "Increase verbosity (can be used multiple times)",
|
||||||
@@ -62,6 +64,7 @@ void setup_argparse(scc_argparse_t *argparse, scc_config_t *config,
|
|||||||
[SCC_HINT_INPUT_FILE] = "输入源文件",
|
[SCC_HINT_INPUT_FILE] = "输入源文件",
|
||||||
[SCC_HINT_INCLUDE_PATH] = "添加系统头文件到搜索路径",
|
[SCC_HINT_INCLUDE_PATH] = "添加系统头文件到搜索路径",
|
||||||
[SCC_HINT_DEFINED_MACRO] = "定义宏",
|
[SCC_HINT_DEFINED_MACRO] = "定义宏",
|
||||||
|
[SCC_HINT_LOG_CONFIG] = "设置模块日志级别 (eg. --log pproc=debug)",
|
||||||
[SCC_HINT_TARGET_DESC] = "目标机器描述(eg. x86_64-pc-windows-msvc)",
|
[SCC_HINT_TARGET_DESC] = "目标机器描述(eg. x86_64-pc-windows-msvc)",
|
||||||
[SCC_HINT_VERBOSE] = "增加详细输出(可多次使用)",
|
[SCC_HINT_VERBOSE] = "增加详细输出(可多次使用)",
|
||||||
|
|
||||||
@@ -106,10 +109,10 @@ void setup_argparse(scc_argparse_t *argparse, scc_config_t *config,
|
|||||||
scc_argparse_spec_setup_string(&opt_output.spec, &(config->output_file));
|
scc_argparse_spec_setup_string(&opt_output.spec, &(config->output_file));
|
||||||
scc_argparse_cmd_add_opt(root, &opt_output);
|
scc_argparse_cmd_add_opt(root, &opt_output);
|
||||||
|
|
||||||
// input file (必需)
|
// input file(s) (必需, 支持多个)
|
||||||
scc_argparse_arg_t arg_input;
|
scc_argparse_arg_t arg_input;
|
||||||
scc_argparse_arg_init(&arg_input, "input", scc_hints[SCC_HINT_INPUT_FILE]);
|
scc_argparse_arg_init(&arg_input, "input", scc_hints[SCC_HINT_INPUT_FILE]);
|
||||||
scc_argparse_spec_setup_string(&arg_input.spec, &(config->input_file));
|
scc_argparse_spec_setup_list(&arg_input.spec, &(config->input_files));
|
||||||
scc_argparse_spec_set_required(&arg_input.spec, true);
|
scc_argparse_spec_set_required(&arg_input.spec, true);
|
||||||
scc_argparse_cmd_add_arg(root, &arg_input);
|
scc_argparse_cmd_add_arg(root, &arg_input);
|
||||||
|
|
||||||
@@ -127,6 +130,13 @@ void setup_argparse(scc_argparse_t *argparse, scc_config_t *config,
|
|||||||
scc_argparse_spec_setup_list(&opt_define.spec, &(config->define_macros));
|
scc_argparse_spec_setup_list(&opt_define.spec, &(config->define_macros));
|
||||||
scc_argparse_cmd_add_opt(root, &opt_define);
|
scc_argparse_cmd_add_opt(root, &opt_define);
|
||||||
|
|
||||||
|
// --log (设置模块日志级别)
|
||||||
|
scc_argparse_opt_t opt_log;
|
||||||
|
scc_argparse_opt_init(&opt_log, 0, "log",
|
||||||
|
scc_hints[SCC_HINT_LOG_CONFIG]);
|
||||||
|
scc_argparse_spec_setup_list(&opt_log.spec, &(config->log_configs));
|
||||||
|
scc_argparse_cmd_add_opt(root, &opt_log);
|
||||||
|
|
||||||
// --entry-point-symbol (设置入口点符号名称)
|
// --entry-point-symbol (设置入口点符号名称)
|
||||||
scc_argparse_opt_t opt_entry_point_symbol;
|
scc_argparse_opt_t opt_entry_point_symbol;
|
||||||
scc_argparse_opt_init(&opt_entry_point_symbol, 0, "entry-point-symbol",
|
scc_argparse_opt_init(&opt_entry_point_symbol, 0, "entry-point-symbol",
|
||||||
|
|||||||
@@ -23,12 +23,13 @@ typedef enum scc_emit_stage {
|
|||||||
} scc_emit_stage_t;
|
} scc_emit_stage_t;
|
||||||
|
|
||||||
typedef struct {
|
typedef struct {
|
||||||
const char *input_file;
|
scc_argparse_list_t input_files;
|
||||||
const char *output_file;
|
const char *output_file;
|
||||||
const char *target_description;
|
const char *target_description;
|
||||||
int verbose;
|
int verbose;
|
||||||
scc_argparse_list_t include_paths;
|
scc_argparse_list_t include_paths;
|
||||||
scc_argparse_list_t define_macros;
|
scc_argparse_list_t define_macros;
|
||||||
|
scc_argparse_list_t log_configs; /* --log module=level */
|
||||||
const char *entry_point_symbol;
|
const char *entry_point_symbol;
|
||||||
|
|
||||||
scc_emit_stage_t emit_stage;
|
scc_emit_stage_t emit_stage;
|
||||||
|
|||||||
344
src/main.c
344
src/main.c
@@ -1,3 +1,6 @@
|
|||||||
|
#define __SCC_CMD_LOG_IMPL__
|
||||||
|
#include "cmd_log.h"
|
||||||
|
|
||||||
#include <argparse.h>
|
#include <argparse.h>
|
||||||
#include <scc_lexer.h>
|
#include <scc_lexer.h>
|
||||||
#include <scc_parser.h>
|
#include <scc_parser.h>
|
||||||
@@ -16,6 +19,7 @@
|
|||||||
#include <scc_ir2mcode.h>
|
#include <scc_ir2mcode.h>
|
||||||
#include <scc_ir2sccf.h>
|
#include <scc_ir2sccf.h>
|
||||||
#include <sccf2pe.h>
|
#include <sccf2pe.h>
|
||||||
|
#include <sccf_linker.h>
|
||||||
|
|
||||||
#define __SCC_TYPE_ABI_WIN_X64_IMPL__
|
#define __SCC_TYPE_ABI_WIN_X64_IMPL__
|
||||||
#include <scc_type_abi_win_x64.h>
|
#include <scc_type_abi_win_x64.h>
|
||||||
@@ -71,6 +75,7 @@ static void print_file(scc_lexer_tok_ring_t *ring, scc_file_t fp) {
|
|||||||
static void tree_dump_output(const char *str, usize len, void *user) {
|
static void tree_dump_output(const char *str, usize len, void *user) {
|
||||||
scc_fprintf(user, "%.*s", (int)len, str);
|
scc_fprintf(user, "%.*s", (int)len, str);
|
||||||
}
|
}
|
||||||
|
|
||||||
static inline int mir_dump(scc_file_t fp, scc_mir_module_t *mir_module) {
|
static inline int mir_dump(scc_file_t fp, scc_mir_module_t *mir_module) {
|
||||||
scc_tree_dump_t tree_dump;
|
scc_tree_dump_t tree_dump;
|
||||||
scc_mir_dump_ctx_t mir_dump_ctx;
|
scc_mir_dump_ctx_t mir_dump_ctx;
|
||||||
@@ -87,85 +92,35 @@ static inline int mir_dump(scc_file_t fp, scc_mir_module_t *mir_module) {
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
int main(int argc, const char **argv, const char **envp) {
|
// Compile a single source file to an SCCF builder.
|
||||||
init_platform();
|
// Returns 0 on success, non-zero on error.
|
||||||
|
// The caller must keep the builder alive until after linking.
|
||||||
#ifndef SCC_DEFAULT_ARGPARSE_LANG
|
static int compile_file_to_sccf(const char *input_file, scc_config_t *config,
|
||||||
#define SCC_DEFAULT_ARGPARSE_LANG SCC_ARGPARSE_LANG_ZH
|
sccf_builder_t *builder) {
|
||||||
#endif
|
|
||||||
|
|
||||||
scc_argparse_lang_t argparse_lang = SCC_DEFAULT_ARGPARSE_LANG;
|
|
||||||
for (const char **env = envp; *env != nullptr; env++) {
|
|
||||||
const char *env_str = *env;
|
|
||||||
if (scc_strcmp(env_str, "LANG=zh_CN.UTF-8") == 0) {
|
|
||||||
argparse_lang = SCC_ARGPARSE_LANG_ZH;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
scc_config_t config = {
|
|
||||||
.input_file = nullptr,
|
|
||||||
.verbose = 0,
|
|
||||||
.output_file = nullptr,
|
|
||||||
.entry_point_symbol = nullptr,
|
|
||||||
.emit_stage = SCC_EMIT_STAGE_DEFAULT,
|
|
||||||
.target_description = "x86_64-pc-windows-msvc",
|
|
||||||
};
|
|
||||||
scc_vec_init(config.include_paths);
|
|
||||||
|
|
||||||
scc_argparse_t argparse;
|
|
||||||
setup_argparse(&argparse, &config, argparse_lang);
|
|
||||||
int ret = scc_argparse_parse(&argparse, argc, argv);
|
|
||||||
if (ret != 0) {
|
|
||||||
scc_argparse_drop(&argparse);
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
scc_argparse_drop(&argparse);
|
|
||||||
|
|
||||||
scc_file_t fp = nullptr;
|
|
||||||
if (config.output_file) {
|
|
||||||
cbool is_stdout = scc_strcmp(config.output_file, "-") == 0;
|
|
||||||
if (!is_stdout) {
|
|
||||||
fp = scc_fopen(config.output_file, SCC_FILE_WRITE);
|
|
||||||
if (fp == nullptr) {
|
|
||||||
LOG_FATAL("Failed to open file %s", config.output_file);
|
|
||||||
return 1;
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
fp = scc_stdout;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
int error_code = 0;
|
int error_code = 0;
|
||||||
cbool need_end = false;
|
|
||||||
scc_sstream_t sstream;
|
scc_sstream_t sstream;
|
||||||
error_code = scc_sstream_init(&sstream, config.input_file, 1024);
|
error_code = scc_sstream_init(&sstream, input_file, 1024);
|
||||||
if (error_code) {
|
if (error_code) {
|
||||||
goto sstream_drop;
|
return error_code;
|
||||||
need_end = true;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
LOG_INFO("=== phase 1/6: lexing '%s' ===", input_file);
|
||||||
scc_lexer_t lexer;
|
scc_lexer_t lexer;
|
||||||
scc_lexer_init(&lexer, scc_sstream_to_ring(&sstream));
|
scc_lexer_init(&lexer, scc_sstream_to_ring(&sstream));
|
||||||
if (config.emit_stage == SCC_EMIT_STAGE_LEX) {
|
if (config->emit_stage == SCC_EMIT_STAGE_LEX) {
|
||||||
scc_lexer_tok_ring_t *tok_ring =
|
// Early-lex is handled per-file at call site
|
||||||
scc_lexer_to_ring(&lexer, 8, fp == nullptr ? false : true);
|
scc_lexer_drop(&lexer);
|
||||||
if (fp == nullptr) {
|
scc_sstream_drop(&sstream);
|
||||||
print_ring(tok_ring, config.verbose);
|
return -1;
|
||||||
} else {
|
|
||||||
print_file(tok_ring, fp);
|
|
||||||
}
|
|
||||||
scc_lexer_drop_ring(tok_ring);
|
|
||||||
need_end = true;
|
|
||||||
goto lexer_drop;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
LOG_INFO("=== phase 2/6: preprocessing '%s' ===", input_file);
|
||||||
scc_pproc_t pproc;
|
scc_pproc_t pproc;
|
||||||
scc_pproc_init(&pproc, scc_lexer_to_ring(&lexer, 8, true));
|
scc_pproc_init(&pproc, scc_lexer_to_ring(&lexer, 8, true));
|
||||||
// FIXME maybe using config to got download path and add include path
|
|
||||||
scc_pproc_add_include_path_cstr(&pproc, "./.scc_include");
|
scc_pproc_add_include_path_cstr(&pproc, "./.scc_include");
|
||||||
scc_vec_foreach(config.include_paths, i) {
|
scc_vec_foreach(config->include_paths, i) {
|
||||||
scc_pproc_add_include_path_cstr(&pproc,
|
scc_pproc_add_include_path_cstr(&pproc,
|
||||||
scc_vec_at(config.include_paths, i));
|
scc_vec_at(config->include_paths, i));
|
||||||
}
|
}
|
||||||
scc_lexer_tok_vec_t pproc_tok_vec;
|
scc_lexer_tok_vec_t pproc_tok_vec;
|
||||||
scc_vec_init(pproc_tok_vec);
|
scc_vec_init(pproc_tok_vec);
|
||||||
@@ -191,6 +146,190 @@ int main(int argc, const char **argv, const char **envp) {
|
|||||||
scc_pproc_add_object_macro(&pproc.macro_table,
|
scc_pproc_add_object_macro(&pproc.macro_table,
|
||||||
&pproc_predefined_macros[i], &pproc_tok_vec);
|
&pproc_predefined_macros[i], &pproc_tok_vec);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
scc_lexer_tok_ring_t *tok_ring =
|
||||||
|
scc_pproc_to_ring(&pproc, 1024, false, false);
|
||||||
|
LOG_INFO("=== phase 3/6: parsing '%s' ===", input_file);
|
||||||
|
scc_parser_t parser;
|
||||||
|
scc_ast_module_t ast_module;
|
||||||
|
scc_ast_module_init(&ast_module);
|
||||||
|
scc_sema_ctx_t sema_ctx;
|
||||||
|
scc_sema_init(&sema_ctx, &ast_module);
|
||||||
|
scc_parser_init(&parser, tok_ring, &ast_module, &sema_ctx);
|
||||||
|
scc_ast_translation_unit_t *translation_unit =
|
||||||
|
scc_parse_translation_unit(&parser);
|
||||||
|
if (parser.errcode != 0) {
|
||||||
|
error_code = parser.errcode;
|
||||||
|
goto cleanup_pproc;
|
||||||
|
}
|
||||||
|
|
||||||
|
LOG_INFO("=== phase 4/6: AST -> HIR ===");
|
||||||
|
scc_ast2ir_ctx_t ast2ir_ctx;
|
||||||
|
scc_hir_cprog_t cprog;
|
||||||
|
scc_hir_cprog_init(&cprog, &SCC_TYPE_ABI_WIN_X64);
|
||||||
|
scc_ast2ir_ctx_init(&ast2ir_ctx, &SCC_TYPE_ABI_WIN_X64, &ast_module,
|
||||||
|
&cprog);
|
||||||
|
scc_ast2ir_run(&ast2ir_ctx, translation_unit);
|
||||||
|
scc_ast2ir_ctx_drop(&ast2ir_ctx);
|
||||||
|
|
||||||
|
LOG_INFO("=== phase 5/6: HIR -> LIR -> MIR ===");
|
||||||
|
// HIR -> LIR
|
||||||
|
scc_lir_module_t lir_module;
|
||||||
|
scc_lir_module_init(&lir_module);
|
||||||
|
scc_hir2lir(&lir_module, &cprog);
|
||||||
|
|
||||||
|
// LIR -> MIR
|
||||||
|
scc_mir_module_t mir_module;
|
||||||
|
scc_mir_module_init(&mir_module);
|
||||||
|
scc_lir2mir(&mir_module, &lir_module);
|
||||||
|
|
||||||
|
// MIR passes
|
||||||
|
scc_mir_pass(&mir_module, SCC_MIR_STAGE_ANY);
|
||||||
|
|
||||||
|
LOG_INFO("=== phase 6/6: MIR -> SCCF ===");
|
||||||
|
// MIR -> SCCF
|
||||||
|
// NOTE: scc_ir2sccf calls sccf_builder_init(builder) internally
|
||||||
|
scc_ir2sccf(builder, &mir_module);
|
||||||
|
|
||||||
|
// Cleanup per-file resources (reverse order)
|
||||||
|
scc_mir_module_drop(&mir_module);
|
||||||
|
scc_lir_module_drop(&lir_module);
|
||||||
|
scc_hir_cprog_drop(&cprog);
|
||||||
|
scc_sema_drop(&sema_ctx);
|
||||||
|
scc_parser_drop(&parser);
|
||||||
|
scc_pproc_drop(&pproc);
|
||||||
|
scc_lexer_drop(&lexer);
|
||||||
|
scc_sstream_drop(&sstream);
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
cleanup_pproc:
|
||||||
|
scc_pproc_drop(&pproc);
|
||||||
|
scc_lexer_drop(&lexer);
|
||||||
|
scc_sstream_drop(&sstream);
|
||||||
|
return error_code;
|
||||||
|
}
|
||||||
|
|
||||||
|
int main(int argc, const char **argv, const char **envp) {
|
||||||
|
init_platform();
|
||||||
|
|
||||||
|
#ifndef SCC_DEFAULT_ARGPARSE_LANG
|
||||||
|
#define SCC_DEFAULT_ARGPARSE_LANG SCC_ARGPARSE_LANG_ZH
|
||||||
|
#endif
|
||||||
|
|
||||||
|
scc_argparse_lang_t argparse_lang = SCC_DEFAULT_ARGPARSE_LANG;
|
||||||
|
for (const char **env = envp; *env != nullptr; env++) {
|
||||||
|
const char *env_str = *env;
|
||||||
|
if (scc_strcmp(env_str, "LANG=zh_CN.UTF-8") == 0) {
|
||||||
|
argparse_lang = SCC_ARGPARSE_LANG_ZH;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
scc_config_t config = {
|
||||||
|
.verbose = 0,
|
||||||
|
.output_file = nullptr,
|
||||||
|
.entry_point_symbol = nullptr,
|
||||||
|
.emit_stage = SCC_EMIT_STAGE_DEFAULT,
|
||||||
|
.target_description = "x86_64-pc-windows-msvc",
|
||||||
|
};
|
||||||
|
scc_vec_init(config.input_files);
|
||||||
|
scc_vec_init(config.include_paths);
|
||||||
|
scc_vec_init(config.define_macros);
|
||||||
|
scc_vec_init(config.log_configs);
|
||||||
|
|
||||||
|
scc_argparse_t argparse;
|
||||||
|
setup_argparse(&argparse, &config, argparse_lang);
|
||||||
|
int ret = scc_argparse_parse(&argparse, argc, argv);
|
||||||
|
if (ret != 0) {
|
||||||
|
scc_argparse_drop(&argparse);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
scc_argparse_drop(&argparse);
|
||||||
|
|
||||||
|
// // Apply log configuration from --log and -v
|
||||||
|
// scc_log_set_verbosity(config.verbose);
|
||||||
|
// scc_vec_foreach(config.log_configs, i) {
|
||||||
|
// scc_log_apply_config(scc_vec_at(config.log_configs, i));
|
||||||
|
// }
|
||||||
|
|
||||||
|
usize num_inputs = scc_vec_size(config.input_files);
|
||||||
|
if (num_inputs == 0) {
|
||||||
|
LOG_ERROR("no input files");
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
scc_file_t fp = nullptr;
|
||||||
|
if (config.output_file) {
|
||||||
|
cbool is_stdout = scc_strcmp(config.output_file, "-") == 0;
|
||||||
|
if (!is_stdout) {
|
||||||
|
fp = scc_fopen(config.output_file, SCC_FILE_WRITE);
|
||||||
|
if (fp == nullptr) {
|
||||||
|
LOG_FATAL("Failed to open file %s", config.output_file);
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
fp = scc_stdout;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Single-file mode: original fast path
|
||||||
|
if (num_inputs == 1) {
|
||||||
|
const char *input_file = scc_vec_at(config.input_files, 0);
|
||||||
|
|
||||||
|
scc_sstream_t sstream;
|
||||||
|
int error_code = scc_sstream_init(&sstream, input_file, 1024);
|
||||||
|
if (error_code) {
|
||||||
|
return error_code;
|
||||||
|
}
|
||||||
|
|
||||||
|
scc_lexer_t lexer;
|
||||||
|
scc_lexer_init(&lexer, scc_sstream_to_ring(&sstream));
|
||||||
|
if (config.emit_stage == SCC_EMIT_STAGE_LEX) {
|
||||||
|
scc_lexer_tok_ring_t *tok_ring =
|
||||||
|
scc_lexer_to_ring(&lexer, 8, fp == nullptr ? false : true);
|
||||||
|
if (fp == nullptr) {
|
||||||
|
print_ring(tok_ring, config.verbose);
|
||||||
|
} else {
|
||||||
|
print_file(tok_ring, fp);
|
||||||
|
}
|
||||||
|
scc_lexer_drop_ring(tok_ring);
|
||||||
|
scc_lexer_drop(&lexer);
|
||||||
|
scc_sstream_drop(&sstream);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
scc_pproc_t pproc;
|
||||||
|
scc_pproc_init(&pproc, scc_lexer_to_ring(&lexer, 8, true));
|
||||||
|
scc_pproc_add_include_path_cstr(&pproc, "./.scc_include");
|
||||||
|
scc_vec_foreach(config.include_paths, i) {
|
||||||
|
scc_pproc_add_include_path_cstr(
|
||||||
|
&pproc, scc_vec_at(config.include_paths, i));
|
||||||
|
}
|
||||||
|
scc_lexer_tok_vec_t pproc_tok_vec;
|
||||||
|
scc_vec_init(pproc_tok_vec);
|
||||||
|
scc_lexer_tok_t tok = {
|
||||||
|
.lexeme = scc_str_from_cstr("1"),
|
||||||
|
.type = SCC_TOK_INT_LITERAL,
|
||||||
|
.loc.name = "<internal>",
|
||||||
|
.loc.line = 0,
|
||||||
|
.loc.col = 0,
|
||||||
|
.loc.offset = 0,
|
||||||
|
};
|
||||||
|
scc_vec_push(pproc_tok_vec, tok);
|
||||||
|
scc_str_t pproc_predefined_macros[] = {
|
||||||
|
scc_str_from_cstr("__SCC__"),
|
||||||
|
scc_str_from_cstr("_WIN64"),
|
||||||
|
scc_str_from_cstr("_WIN32"),
|
||||||
|
scc_str_from_cstr("__x86_64__"),
|
||||||
|
};
|
||||||
|
for (usize i = 0; i < SCC_ARRLEN(pproc_predefined_macros); i += 1) {
|
||||||
|
scc_vec_init(pproc_tok_vec);
|
||||||
|
scc_lexer_tok_t coped_tok = scc_lexer_tok_copy(&tok);
|
||||||
|
scc_vec_push(pproc_tok_vec, coped_tok);
|
||||||
|
scc_pproc_add_object_macro(&pproc.macro_table,
|
||||||
|
&pproc_predefined_macros[i],
|
||||||
|
&pproc_tok_vec);
|
||||||
|
}
|
||||||
if (config.emit_stage == SCC_EMIT_STAGE_PP) {
|
if (config.emit_stage == SCC_EMIT_STAGE_PP) {
|
||||||
scc_lexer_tok_ring_t *tok_ring =
|
scc_lexer_tok_ring_t *tok_ring =
|
||||||
scc_pproc_to_ring(&pproc, 8, true, true);
|
scc_pproc_to_ring(&pproc, 8, true, true);
|
||||||
@@ -199,8 +338,10 @@ int main(int argc, const char **argv, const char **envp) {
|
|||||||
} else {
|
} else {
|
||||||
print_file(tok_ring, fp);
|
print_file(tok_ring, fp);
|
||||||
}
|
}
|
||||||
need_end = true;
|
scc_pproc_drop(&pproc);
|
||||||
goto pproc_drop;
|
scc_lexer_drop(&lexer);
|
||||||
|
scc_sstream_drop(&sstream);
|
||||||
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
scc_lexer_tok_ring_t *tok_ring =
|
scc_lexer_tok_ring_t *tok_ring =
|
||||||
@@ -214,20 +355,19 @@ int main(int argc, const char **argv, const char **envp) {
|
|||||||
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) {
|
||||||
|
scc_sema_drop(&sema_ctx);
|
||||||
|
scc_parser_drop(&parser);
|
||||||
|
scc_pproc_drop(&pproc);
|
||||||
|
scc_lexer_drop(&lexer);
|
||||||
|
scc_sstream_drop(&sstream);
|
||||||
return parser.errcode;
|
return parser.errcode;
|
||||||
}
|
}
|
||||||
|
|
||||||
scc_sema_drop(&sema_ctx);
|
scc_sema_drop(&sema_ctx);
|
||||||
scc_parser_drop(&parser);
|
scc_parser_drop(&parser);
|
||||||
pproc_drop:
|
|
||||||
scc_pproc_drop(&pproc);
|
scc_pproc_drop(&pproc);
|
||||||
lexer_drop:
|
|
||||||
scc_lexer_drop(&lexer);
|
scc_lexer_drop(&lexer);
|
||||||
sstream_drop:
|
|
||||||
scc_sstream_drop(&sstream);
|
scc_sstream_drop(&sstream);
|
||||||
if (error_code || need_end) {
|
|
||||||
return error_code;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (config.emit_stage == SCC_EMIT_STAGE_AST) {
|
if (config.emit_stage == SCC_EMIT_STAGE_AST) {
|
||||||
scc_tree_dump_t tree_dump;
|
scc_tree_dump_t tree_dump;
|
||||||
@@ -259,7 +399,6 @@ sstream_drop:
|
|||||||
scc_tree_dump_init(&tree_dump, false);
|
scc_tree_dump_init(&tree_dump, false);
|
||||||
}
|
}
|
||||||
scc_hir_dump_init(&ir_dump_ctx, &tree_dump, &cprog);
|
scc_hir_dump_init(&ir_dump_ctx, &tree_dump, &cprog);
|
||||||
// scc_ir_dump_cprog(&ir_dump_ctx);
|
|
||||||
scc_hir_dump_cprog_linear(&ir_dump_ctx);
|
scc_hir_dump_cprog_linear(&ir_dump_ctx);
|
||||||
|
|
||||||
scc_tree_dump_flush(&tree_dump, tree_dump_output, GET_VALID_FP(fp));
|
scc_tree_dump_flush(&tree_dump, tree_dump_output, GET_VALID_FP(fp));
|
||||||
@@ -279,7 +418,6 @@ sstream_drop:
|
|||||||
scc_tree_dump_init(&tree_dump, false);
|
scc_tree_dump_init(&tree_dump, false);
|
||||||
}
|
}
|
||||||
scc_lir_dump_init(&lir_dump_ctx, &tree_dump, &lir_module);
|
scc_lir_dump_init(&lir_dump_ctx, &tree_dump, &lir_module);
|
||||||
// scc_ir_dump_cprog(&ir_dump_ctx);
|
|
||||||
scc_lir_dump_module(&lir_dump_ctx);
|
scc_lir_dump_module(&lir_dump_ctx);
|
||||||
|
|
||||||
scc_tree_dump_flush(&tree_dump, tree_dump_output, GET_VALID_FP(fp));
|
scc_tree_dump_flush(&tree_dump, tree_dump_output, GET_VALID_FP(fp));
|
||||||
@@ -317,25 +455,23 @@ sstream_drop:
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
usize mcode_size = scc_mcode_size(&mcode);
|
usize mcode_size = scc_mcode_size(&mcode);
|
||||||
usize ret = scc_fwrite(fp, scc_mcode_unsafe_data(&mcode), mcode_size);
|
usize fwritten =
|
||||||
if (ret != mcode_size) {
|
scc_fwrite(fp, scc_mcode_unsafe_data(&mcode), mcode_size);
|
||||||
LOG_ERROR("write flatbin failed, write %zu but need write %zu\n",
|
if (fwritten != mcode_size) {
|
||||||
ret, mcode_size);
|
LOG_ERROR("write flatbin failed, write %zu but need %zu",
|
||||||
|
fwritten, mcode_size);
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Single-file: compile to SCCF then directly to PE
|
||||||
sccf_builder_t sccf_builder = {0};
|
sccf_builder_t sccf_builder = {0};
|
||||||
sccf_builder_init(&sccf_builder);
|
|
||||||
scc_ir2sccf(&sccf_builder, &mir_module);
|
scc_ir2sccf(&sccf_builder, &mir_module);
|
||||||
sccf_builder_set_entry_symbol_name(&sccf_builder,
|
sccf_builder_set_entry_symbol_name(&sccf_builder,
|
||||||
config.entry_point_symbol);
|
config.entry_point_symbol);
|
||||||
const sccf_t *sccf = sccf_builder_to_sccf(&sccf_builder);
|
const sccf_t *sccf = sccf_builder_to_sccf(&sccf_builder);
|
||||||
if (config.emit_stage == SCC_EMIT_STAGE_SCCF) {
|
if (config.emit_stage == SCC_EMIT_STAGE_SCCF) {
|
||||||
// sccf_buffer_t buffer;
|
|
||||||
// scc_vec_init(buffer);
|
|
||||||
// sccf_builder_to_buffer(&sccf_builder, &buffer);
|
|
||||||
if (fp == nullptr) {
|
if (fp == nullptr) {
|
||||||
scc_printf("output exe at %s\n", config.output_file);
|
scc_printf("output exe at %s\n", config.output_file);
|
||||||
} else {
|
} else {
|
||||||
@@ -359,3 +495,43 @@ sstream_drop:
|
|||||||
Panic("unknown emit stage");
|
Panic("unknown emit stage");
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Multi-file mode (num_inputs > 1)
|
||||||
|
if (config.emit_stage != SCC_EMIT_STAGE_DEFAULT) {
|
||||||
|
LOG_ERROR("--emit is not supported with multiple input files");
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
// First pass: compile each file to SCCF
|
||||||
|
sccf_linker_t linker;
|
||||||
|
sccf_linker_init(&linker);
|
||||||
|
sccf_linker_set_entry_symbol_name(&linker, config.entry_point_symbol);
|
||||||
|
|
||||||
|
scc_vec_foreach(config.input_files, i) {
|
||||||
|
const char *input = scc_vec_at(config.input_files, i);
|
||||||
|
sccf_builder_t builder = {0};
|
||||||
|
|
||||||
|
int err = compile_file_to_sccf(input, &config, &builder);
|
||||||
|
if (err != 0) {
|
||||||
|
return err;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Transfer this file's SCCF to the linker.
|
||||||
|
// The builder data stays alive on the heap; the linker stores a shallow
|
||||||
|
// copy. We must NOT drop/free the builder while the linker references
|
||||||
|
// it.
|
||||||
|
sccf_linker_add_sccf(&linker, sccf_builder_to_sccf(&builder));
|
||||||
|
}
|
||||||
|
|
||||||
|
// Second pass: link all SCCF modules and emit PE
|
||||||
|
const sccf_t *linked = sccf_linker_link(&linker);
|
||||||
|
scc_pe_builder_t pe_builder;
|
||||||
|
sccf2pe(&pe_builder, linked);
|
||||||
|
if (fp == nullptr) {
|
||||||
|
scc_printf("output exe at %s\n", config.output_file);
|
||||||
|
} else {
|
||||||
|
scc_pe_dump_to_file(&pe_builder, config.output_file);
|
||||||
|
}
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user