refactor(argparse): 将null替换为nullptr以提高C++兼容性
- 在argparse库中将所有null指针常量替换为nullptr - 更新头文件和源文件中的指针初始化和比较操作 - 修改测试文件中的相关断言检查 - 更新AST定义文件中的注释说明
This commit is contained in:
@@ -148,11 +148,11 @@ void scc_argparse_print_error(scc_argparse_context_t *ctx,
|
||||
|
||||
static inline void scc_argparse_spec_init(scc_argparse_spec_t *spec) {
|
||||
spec->value_type = SCC_ARGPARSE_VAL_TYPE_STRING;
|
||||
spec->raw_value = null;
|
||||
spec->store.ptr_store = null;
|
||||
spec->raw_value = nullptr;
|
||||
spec->store.ptr_store = nullptr;
|
||||
|
||||
spec->choices.count = 0;
|
||||
spec->choices.values = null;
|
||||
spec->choices.values = nullptr;
|
||||
|
||||
spec->flag_required = false;
|
||||
spec->flag_store_as_count = false;
|
||||
|
||||
@@ -5,7 +5,7 @@ void scc_argparse_init(scc_argparse_t *parser, const char *program_name,
|
||||
parser->prog_name = program_name;
|
||||
parser->version = "0.1.0";
|
||||
parser->description = description;
|
||||
parser->epilog = null;
|
||||
parser->epilog = nullptr;
|
||||
|
||||
parser->lang = SCC_ARGPARSE_LANG_EN;
|
||||
parser->need_help = true;
|
||||
@@ -26,7 +26,7 @@ void scc_argparse_drop(scc_argparse_t *parser) {
|
||||
static inline scc_argparse_cmd_t *is_subcommand(scc_argparse_cmd_t *cmd,
|
||||
const char *name) {
|
||||
if (!scc_vec_size(cmd->subcmds)) {
|
||||
return null;
|
||||
return nullptr;
|
||||
}
|
||||
scc_vec_foreach(cmd->subcmds, i) {
|
||||
scc_argparse_cmd_t *subcmd = &scc_vec_at(cmd->subcmds, i);
|
||||
@@ -34,7 +34,7 @@ static inline scc_argparse_cmd_t *is_subcommand(scc_argparse_cmd_t *cmd,
|
||||
return subcmd;
|
||||
}
|
||||
}
|
||||
return null;
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
static inline void parse_cmd(scc_optparse_t *optparse,
|
||||
@@ -86,7 +86,7 @@ static inline void parse_cmd(scc_optparse_t *optparse,
|
||||
scc_optparse_set(optparse, opts->data);
|
||||
}
|
||||
static void push_help(scc_argparse_cmd_t *cmd) {
|
||||
if (cmd == null) {
|
||||
if (cmd == nullptr) {
|
||||
return;
|
||||
}
|
||||
scc_vec_push(cmd->opts, ((scc_argparse_opt_t){
|
||||
@@ -144,7 +144,8 @@ static int validate_and_cleanup(scc_argparse_context_t *ctx,
|
||||
// 检查必需参数是否都已提供
|
||||
scc_vec_foreach(ctx->current_cmd->args, i) {
|
||||
scc_argparse_arg_t *arg = &scc_vec_at(ctx->current_cmd->args, i);
|
||||
if (arg->spec.flag_required && *arg->spec.store.str_store == NULL) {
|
||||
if (arg->spec.flag_required &&
|
||||
*arg->spec.store.str_store == nullptr) {
|
||||
errcode = SCC_ARGPARSE_ERR_MISSING_ARG;
|
||||
scc_argparse_print_error(ctx, errcode);
|
||||
break;
|
||||
@@ -190,7 +191,7 @@ static int handle_option(scc_argparse_context_t *ctx, scc_argparse_t *parser) {
|
||||
*opt->spec.store.str_store = ctx->result.value;
|
||||
}
|
||||
|
||||
// // opt value == null or value != null
|
||||
// // opt value == nullptr or value != nullptr
|
||||
// scc_argparse_opt_t *org_opt =
|
||||
// (scc_argparse_opt_t *)opt_res.opt->user_data;
|
||||
// if (parser->need_help) {
|
||||
@@ -218,7 +219,7 @@ static int handle_positional_arg(scc_argparse_context_t *ctx,
|
||||
(void)parser; // TODO
|
||||
scc_argparse_cmd_t *subcmd =
|
||||
is_subcommand(ctx->current_cmd, ctx->result.value);
|
||||
if (subcmd != NULL) {
|
||||
if (subcmd != nullptr) {
|
||||
ctx->current_cmd = subcmd;
|
||||
parse_cmd(&ctx->optparse, &ctx->opts, ctx->current_cmd);
|
||||
return SCC_ARGPARSE_ERR_NONE;
|
||||
@@ -239,7 +240,7 @@ static int handle_positional_arg(scc_argparse_context_t *ctx,
|
||||
// scc_argparse_cmd_t *cmd = is_subcommand(current_cmd,
|
||||
// opt_res.value);
|
||||
|
||||
// if (cmd != null) {
|
||||
// if (cmd != nullptr) {
|
||||
// current_cmd = cmd;
|
||||
// parse_cmd(&optparse, &opts, current_cmd);
|
||||
// } else {
|
||||
@@ -275,9 +276,9 @@ int scc_argparse_parse(scc_argparse_t *parser, int argc, const char **argv) {
|
||||
break;
|
||||
}
|
||||
|
||||
if (ctx.result.opt != null) {
|
||||
if (ctx.result.opt != nullptr) {
|
||||
errcode = handle_option(&ctx, parser);
|
||||
} else if (ctx.result.value != null) {
|
||||
} else if (ctx.result.value != nullptr) {
|
||||
errcode = handle_positional_arg(&ctx, parser);
|
||||
} else {
|
||||
UNREACHABLE(); // 不应到达此处
|
||||
|
||||
@@ -174,8 +174,8 @@ void scc_argparse_print_help(scc_argparse_t *parser, scc_argparse_cmd_t *cmd) {
|
||||
|
||||
const char *scc_argparse_find_similar_arg(scc_argparse_cmd_t *cmd,
|
||||
const char *arg) {
|
||||
if (arg == null || cmd == null) {
|
||||
return null;
|
||||
if (arg == nullptr || cmd == nullptr) {
|
||||
return nullptr;
|
||||
}
|
||||
if (arg[0] == '-' && arg[1] == '-' && arg[2] != '\0') {
|
||||
// opt arg
|
||||
|
||||
@@ -45,21 +45,21 @@ void test_simple_short_options(void) {
|
||||
// 解析第一个选项 -h
|
||||
TEST_CHECK(scc_optparse_parse(&parser, &res) != 0);
|
||||
TEST_CHECK(res.error == SCC_OPT_ERROR_NONE);
|
||||
TEST_CHECK(res.opt != NULL);
|
||||
TEST_CHECK(res.opt != nullptr);
|
||||
TEST_CHECK(res.opt && res.opt->short_name == 'h');
|
||||
TEST_CHECK(res.value == NULL);
|
||||
TEST_CHECK(res.value == nullptr);
|
||||
|
||||
// 解析第二个选项 -v
|
||||
TEST_CHECK(scc_optparse_parse(&parser, &res) != 0);
|
||||
TEST_CHECK(res.error == SCC_OPT_ERROR_NONE);
|
||||
TEST_CHECK(res.opt != NULL);
|
||||
TEST_CHECK(res.opt != nullptr);
|
||||
TEST_CHECK(res.opt && res.opt->short_name == 'v');
|
||||
TEST_CHECK(res.value == NULL);
|
||||
TEST_CHECK(res.value == nullptr);
|
||||
|
||||
// 没有更多选项
|
||||
TEST_CHECK(scc_optparse_parse(&parser, &res) == 0);
|
||||
TEST_CHECK(res.opt == NULL);
|
||||
TEST_CHECK(res.value == NULL);
|
||||
TEST_CHECK(res.opt == nullptr);
|
||||
TEST_CHECK(res.value == nullptr);
|
||||
}
|
||||
|
||||
void test_simple_position_arg(void) {
|
||||
@@ -70,19 +70,19 @@ void test_simple_position_arg(void) {
|
||||
// 解析第一个选项
|
||||
TEST_CHECK(scc_optparse_parse(&parser, &res) != 0);
|
||||
TEST_CHECK(res.error == SCC_OPT_ERROR_NONE);
|
||||
TEST_CHECK(res.opt == NULL);
|
||||
TEST_CHECK(res.opt == nullptr);
|
||||
TEST_CHECK(strcmp(res.value, "a") == 0);
|
||||
|
||||
// 解析第二个选项
|
||||
TEST_CHECK(scc_optparse_parse(&parser, &res) != 0);
|
||||
TEST_CHECK(res.error == SCC_OPT_ERROR_NONE);
|
||||
TEST_CHECK(res.opt == NULL);
|
||||
TEST_CHECK(res.opt == nullptr);
|
||||
TEST_CHECK(strcmp(res.value, "b") == 0);
|
||||
|
||||
// 没有更多选项
|
||||
TEST_CHECK(scc_optparse_parse(&parser, &res) == 0);
|
||||
TEST_CHECK(res.opt == NULL);
|
||||
TEST_CHECK(res.value == NULL);
|
||||
TEST_CHECK(res.opt == nullptr);
|
||||
TEST_CHECK(res.value == nullptr);
|
||||
}
|
||||
|
||||
// 测试3: 带参数的短选项
|
||||
@@ -95,14 +95,14 @@ void test_short_options_with_args(void) {
|
||||
// 解析 -f file.txt
|
||||
scc_optparse_parse(&parser, &res);
|
||||
TEST_CHECK(res.error == SCC_OPT_ERROR_NONE);
|
||||
TEST_CHECK(res.opt != NULL);
|
||||
TEST_CHECK(res.opt != nullptr);
|
||||
TEST_CHECK(res.opt && res.opt->short_name == 'f');
|
||||
TEST_CHECK(strcmp(res.value, "file.txt") == 0);
|
||||
|
||||
// 解析 -o output.txt
|
||||
scc_optparse_parse(&parser, &res);
|
||||
TEST_CHECK(res.error == SCC_OPT_ERROR_NONE);
|
||||
TEST_CHECK(res.opt != NULL);
|
||||
TEST_CHECK(res.opt != nullptr);
|
||||
TEST_CHECK(res.opt && res.opt->short_name == 'o');
|
||||
TEST_CHECK(strcmp(res.value, "output.txt") == 0);
|
||||
}
|
||||
@@ -119,20 +119,20 @@ void test_long_options(void) {
|
||||
// 解析 --help
|
||||
scc_optparse_parse(&parser, &res);
|
||||
TEST_CHECK(res.error == SCC_OPT_ERROR_NONE);
|
||||
TEST_CHECK(res.opt != NULL);
|
||||
TEST_CHECK(res.opt != nullptr);
|
||||
TEST_CHECK(res.opt && strcmp(res.opt->long_name, "help") == 0);
|
||||
|
||||
// 解析 --file=test.txt
|
||||
scc_optparse_parse(&parser, &res);
|
||||
TEST_CHECK(res.error == SCC_OPT_ERROR_NONE);
|
||||
TEST_CHECK(res.opt != NULL);
|
||||
TEST_CHECK(res.opt != nullptr);
|
||||
TEST_CHECK(res.opt && strcmp(res.opt->long_name, "file") == 0);
|
||||
TEST_CHECK(strcmp(res.value, "test.txt") == 0);
|
||||
|
||||
// 解析 --output out.txt
|
||||
scc_optparse_parse(&parser, &res);
|
||||
TEST_CHECK(res.error == SCC_OPT_ERROR_NONE);
|
||||
TEST_CHECK(res.opt != NULL);
|
||||
TEST_CHECK(res.opt != nullptr);
|
||||
TEST_CHECK(res.opt && strcmp(res.opt->long_name, "output") == 0);
|
||||
TEST_CHECK(strcmp(res.value, "out.txt") == 0);
|
||||
}
|
||||
@@ -160,13 +160,13 @@ void test_mixed_options_positional(void) {
|
||||
// 解析第一个位置参数
|
||||
scc_optparse_parse(&parser, &res);
|
||||
TEST_CHECK(res.error == SCC_OPT_ERROR_NONE);
|
||||
TEST_CHECK(res.opt == NULL);
|
||||
TEST_CHECK(res.opt == nullptr);
|
||||
TEST_CHECK(strcmp(res.value, "positional1") == 0);
|
||||
|
||||
// 解析第二个位置参数
|
||||
scc_optparse_parse(&parser, &res);
|
||||
TEST_CHECK(res.error == SCC_OPT_ERROR_NONE);
|
||||
TEST_CHECK(res.opt == NULL);
|
||||
TEST_CHECK(res.opt == nullptr);
|
||||
TEST_CHECK(strcmp(res.value, "positional2") == 0);
|
||||
}
|
||||
|
||||
@@ -250,13 +250,13 @@ void test_option_terminator(void) {
|
||||
// 解析 -f (作为位置参数)
|
||||
scc_optparse_parse(&parser, &res);
|
||||
TEST_CHECK(res.error == SCC_OPT_ERROR_NONE);
|
||||
TEST_CHECK(res.opt == NULL);
|
||||
TEST_CHECK(res.opt == nullptr);
|
||||
TEST_CHECK(strcmp(res.value, "-f") == 0);
|
||||
|
||||
// 解析 file.txt (作为位置参数)
|
||||
scc_optparse_parse(&parser, &res);
|
||||
TEST_CHECK(res.error == SCC_OPT_ERROR_NONE);
|
||||
TEST_CHECK(res.opt == NULL);
|
||||
TEST_CHECK(res.opt == nullptr);
|
||||
TEST_CHECK(strcmp(res.value, "file.txt") == 0);
|
||||
}
|
||||
|
||||
@@ -270,8 +270,8 @@ void test_edge_cases(void) {
|
||||
INIT_OPTPARSE(argv1);
|
||||
|
||||
scc_optparse_parse(&parser, &res);
|
||||
TEST_CHECK(res.opt == NULL);
|
||||
TEST_CHECK(res.value == NULL);
|
||||
TEST_CHECK(res.opt == nullptr);
|
||||
TEST_CHECK(res.value == nullptr);
|
||||
|
||||
// 测试空字符串参数
|
||||
const char *argv2[] = {"program", "-f", "", "-o", " "};
|
||||
@@ -302,23 +302,23 @@ void test_multi_argument_option(void) {
|
||||
scc_optparse_parse(&parser, &res);
|
||||
TEST_CHECK(res.error == SCC_OPT_ERROR_NONE);
|
||||
TEST_CHECK(res.opt && res.opt->short_name == 'l');
|
||||
TEST_CHECK(res.value == NULL);
|
||||
TEST_CHECK(res.value == nullptr);
|
||||
|
||||
// 由于 -l 可以接受多个参数,后续的参数应该作为 -l 的值
|
||||
// 但根据当前实现,可能需要多次调用
|
||||
scc_optparse_parse(&parser, &res);
|
||||
TEST_CHECK(res.error == SCC_OPT_ERROR_NONE);
|
||||
TEST_CHECK(res.opt != NULL);
|
||||
TEST_CHECK(res.opt != nullptr);
|
||||
TEST_CHECK(strcmp(res.value, "item1") == 0);
|
||||
|
||||
scc_optparse_parse(&parser, &res);
|
||||
TEST_CHECK(res.error == SCC_OPT_ERROR_NONE);
|
||||
TEST_CHECK(res.opt != NULL);
|
||||
TEST_CHECK(res.opt != nullptr);
|
||||
TEST_CHECK(strcmp(res.value, "item2") == 0);
|
||||
|
||||
scc_optparse_parse(&parser, &res);
|
||||
TEST_CHECK(res.error == SCC_OPT_ERROR_NONE);
|
||||
TEST_CHECK(res.opt != NULL);
|
||||
TEST_CHECK(res.opt != nullptr);
|
||||
TEST_CHECK(strcmp(res.value, "item3") == 0);
|
||||
}
|
||||
|
||||
@@ -344,7 +344,7 @@ void test_long_option_with_equal_no_value(void) {
|
||||
|
||||
scc_optparse_parse(&parser, &res);
|
||||
TEST_CHECK(res.error == SCC_OPT_ERROR_NOT_ENOUGH_ARGS);
|
||||
TEST_CHECK(res.opt != NULL);
|
||||
TEST_CHECK(res.opt != nullptr);
|
||||
TEST_CHECK(res.opt && strcmp(res.opt->long_name, "file") == 0);
|
||||
}
|
||||
|
||||
@@ -382,14 +382,14 @@ void test_combined_short_with_arg(void) {
|
||||
// 解析 -v
|
||||
scc_optparse_parse(&parser, &res);
|
||||
TEST_CHECK(res.error == SCC_OPT_ERROR_NONE);
|
||||
TEST_CHECK(res.opt != NULL);
|
||||
TEST_CHECK(res.opt != nullptr);
|
||||
TEST_CHECK(res.opt && res.opt->short_name == 'v');
|
||||
TEST_CHECK(res.value == NULL);
|
||||
TEST_CHECK(res.value == nullptr);
|
||||
|
||||
// 解析 -finput.txt
|
||||
scc_optparse_parse(&parser, &res);
|
||||
TEST_CHECK(res.error == SCC_OPT_ERROR_NONE);
|
||||
TEST_CHECK(res.opt != NULL);
|
||||
TEST_CHECK(res.opt != nullptr);
|
||||
TEST_CHECK(res.opt && res.opt->short_name == 'f');
|
||||
TEST_CHECK(strcmp(res.value, "input.txt") == 0);
|
||||
}
|
||||
@@ -405,14 +405,14 @@ void test_too_many_arguments(void) {
|
||||
// 解析 -f file1
|
||||
scc_optparse_parse(&parser, &res);
|
||||
TEST_CHECK(res.error == SCC_OPT_ERROR_NONE);
|
||||
TEST_CHECK(res.opt != NULL);
|
||||
TEST_CHECK(res.opt != nullptr);
|
||||
TEST_CHECK(res.opt && res.opt->short_name == 'f');
|
||||
TEST_CHECK(strcmp(res.value, "file1") == 0);
|
||||
|
||||
// 尝试给 -f 第二个参数,应该返回错误
|
||||
scc_optparse_parse(&parser, &res);
|
||||
TEST_CHECK(res.error == SCC_OPT_ERROR_NONE);
|
||||
TEST_CHECK(res.opt == NULL);
|
||||
TEST_CHECK(res.opt == nullptr);
|
||||
TEST_CHECK(strcmp(res.value, "file2") == 0);
|
||||
}
|
||||
|
||||
@@ -438,7 +438,7 @@ void test_mixed_short_and_positional(void) {
|
||||
// 解析位置参数
|
||||
scc_optparse_parse(&parser, &res);
|
||||
TEST_CHECK(res.error == SCC_OPT_ERROR_NONE);
|
||||
TEST_CHECK(res.opt == NULL);
|
||||
TEST_CHECK(res.opt == nullptr);
|
||||
TEST_CHECK(strcmp(res.value, "positional") == 0);
|
||||
}
|
||||
|
||||
@@ -471,7 +471,7 @@ void test_complex_multi_argument(void) {
|
||||
// 第4个参数应该是位置参数
|
||||
scc_optparse_parse(&parser, &res);
|
||||
TEST_CHECK(res.error == SCC_OPT_ERROR_NONE);
|
||||
TEST_CHECK(res.opt == NULL);
|
||||
TEST_CHECK(res.opt == nullptr);
|
||||
TEST_CHECK(strcmp(res.value, "extra") == 0);
|
||||
}
|
||||
|
||||
@@ -487,7 +487,7 @@ void test_long_option_multi_args(void) {
|
||||
scc_optparse_parse(&parser, &res);
|
||||
TEST_CHECK(res.error == SCC_OPT_ERROR_NONE);
|
||||
TEST_CHECK(res.opt && strcmp(res.opt->long_name, "list") == 0);
|
||||
TEST_CHECK(res.value == NULL);
|
||||
TEST_CHECK(res.value == nullptr);
|
||||
|
||||
// 解析 item1
|
||||
scc_optparse_parse(&parser, &res);
|
||||
@@ -518,7 +518,7 @@ void test_empty_long_name(void) {
|
||||
|
||||
scc_optparse_parse(&parser, &res);
|
||||
TEST_CHECK(parser.handle_positional == 1);
|
||||
TEST_CHECK(res.opt == NULL);
|
||||
TEST_CHECK(res.opt == nullptr);
|
||||
TEST_CHECK(strcmp(res.value, "--") == 0);
|
||||
}
|
||||
|
||||
@@ -538,7 +538,7 @@ void test_non_dash_prefix(void) {
|
||||
|
||||
scc_optparse_parse(&parser, &res);
|
||||
TEST_CHECK(res.error == SCC_OPT_ERROR_NONE);
|
||||
TEST_CHECK(res.opt != NULL);
|
||||
TEST_CHECK(res.opt != nullptr);
|
||||
TEST_CHECK(res.opt && res.opt->short_name == 'h');
|
||||
TEST_CHECK(res.opt && res.opt->prefix == '/');
|
||||
}
|
||||
@@ -550,7 +550,7 @@ void test_default_value(void) {
|
||||
// scc_optparse_result_t res;
|
||||
|
||||
// static scc_optparse_opt_t default_opts[] = {
|
||||
// SCC_OPTPARSE_OPT('-', 'o', "output", 0, 1, "default.txt", NULL),
|
||||
// SCC_OPTPARSE_OPT('-', 'o', "output", 0, 1, "default.txt", nullptr),
|
||||
// SCC_OPTPARSE_OPT_END(),
|
||||
// };
|
||||
|
||||
@@ -602,7 +602,7 @@ void test_callback_function(void) {
|
||||
|
||||
// // 调用回调函数
|
||||
// if (res.opt->invoke) {
|
||||
// res.opt->invoke(NULL);
|
||||
// res.opt->invoke(nullptr);
|
||||
// TEST_CHECK(callback_called == 1);
|
||||
// }
|
||||
}
|
||||
@@ -644,7 +644,7 @@ void test_single_dash(void) {
|
||||
|
||||
// 解析单个横杠(通常表示标准输入)
|
||||
scc_optparse_parse(&parser, &res);
|
||||
TEST_CHECK(res.opt == NULL);
|
||||
TEST_CHECK(res.opt == nullptr);
|
||||
TEST_CHECK(strcmp(res.value, "-") == 0);
|
||||
|
||||
// 解析 --
|
||||
@@ -724,5 +724,5 @@ TEST_LIST = {
|
||||
{"test_complex_short_combination", test_complex_short_combination},
|
||||
{"test_single_dash", test_single_dash},
|
||||
{"test_parser_state_reset", test_parser_state_reset},
|
||||
{NULL, NULL},
|
||||
{nullptr, nullptr},
|
||||
};
|
||||
@@ -176,7 +176,7 @@ struct scc_ast_type {
|
||||
} pointer;
|
||||
struct {
|
||||
scc_ast_type_t *element;
|
||||
scc_ast_expr_t *size; // 可为 null <=> 不定长数组
|
||||
scc_ast_expr_t *size; // 可为 nullptr <=> 不定长数组
|
||||
} array;
|
||||
struct {
|
||||
scc_ast_type_t *return_type;
|
||||
@@ -184,7 +184,7 @@ struct scc_ast_type {
|
||||
} function;
|
||||
struct {
|
||||
const char *name;
|
||||
scc_ast_decl_t *decl; // can be null
|
||||
scc_ast_decl_t *decl; // can be nullptr
|
||||
} record;
|
||||
struct {
|
||||
const char *name;
|
||||
@@ -354,7 +354,7 @@ struct scc_ast_stmt {
|
||||
struct {
|
||||
scc_ast_expr_t *cond;
|
||||
scc_ast_stmt_t *then_stmt;
|
||||
scc_ast_stmt_t *opt_else_stmt; // stmt or null
|
||||
scc_ast_stmt_t *opt_else_stmt; // stmt or nullptr
|
||||
} if_stmt;
|
||||
// while do-while 语句
|
||||
struct {
|
||||
@@ -363,9 +363,9 @@ struct scc_ast_stmt {
|
||||
} while_stmt;
|
||||
// for 语句
|
||||
struct {
|
||||
scc_ast_node_t *init; // expr or decl or null
|
||||
scc_ast_expr_t *cond; // 可为 null
|
||||
scc_ast_expr_t *incr; // 可为 null
|
||||
scc_ast_node_t *init; // expr or decl or nullptr
|
||||
scc_ast_expr_t *cond; // 可为 nullptr
|
||||
scc_ast_expr_t *incr; // 可为 nullptr
|
||||
scc_ast_stmt_t *body;
|
||||
} for_stmt;
|
||||
// switch 语句
|
||||
@@ -388,7 +388,7 @@ struct scc_ast_stmt {
|
||||
} jump;
|
||||
// return 语句
|
||||
struct {
|
||||
scc_ast_expr_t *expr; // 可为 null
|
||||
scc_ast_expr_t *expr; // 可为 nullptr
|
||||
} return_stmt;
|
||||
// goto 语句
|
||||
struct {
|
||||
@@ -416,12 +416,12 @@ struct scc_ast_decl {
|
||||
// 变量声明
|
||||
struct {
|
||||
scc_ast_type_t *type;
|
||||
scc_ast_expr_t *init; // 可为 NULL
|
||||
scc_ast_expr_t *init; // 可为 nullptr
|
||||
} var;
|
||||
// 函数声明
|
||||
struct {
|
||||
scc_ast_type_t *type; // 函数类型
|
||||
scc_ast_stmt_t *body; // 可为 null 表示只有声明
|
||||
scc_ast_stmt_t *body; // 可为 nullptr 表示只有声明
|
||||
} func;
|
||||
// 参数声明
|
||||
struct {
|
||||
|
||||
@@ -4,14 +4,14 @@
|
||||
#include "ast_def.h"
|
||||
#include "ast_dump.h"
|
||||
|
||||
// decls can be null but maybe warning
|
||||
// decls can be nullptr but maybe warning
|
||||
static inline void
|
||||
scc_ast_translation_unit_init(scc_ast_translation_unit_t *translation_unit,
|
||||
scc_ast_decl_vec_t *decls, scc_pos_t loc) {
|
||||
Assert(translation_unit != null);
|
||||
Assert(translation_unit != nullptr);
|
||||
translation_unit->base.type = SCC_AST_TRANSLATION_UNIT;
|
||||
translation_unit->base.loc = loc;
|
||||
if (decls == null) {
|
||||
if (decls == nullptr) {
|
||||
scc_vec_init(translation_unit->declarations);
|
||||
} else {
|
||||
translation_unit->declarations = *decls;
|
||||
@@ -22,21 +22,21 @@ scc_ast_translation_unit_init(scc_ast_translation_unit_t *translation_unit,
|
||||
static inline void scc_ast_decl_list_init(scc_ast_decl_t *decl,
|
||||
scc_ast_decl_vec_t *list_move,
|
||||
scc_pos_t loc) {
|
||||
Assert(decl != null && list_move != null);
|
||||
Assert(decl != nullptr && list_move != nullptr);
|
||||
decl->base.loc = loc;
|
||||
decl->base.type = SCC_AST_DECL_LIST;
|
||||
decl->name = null;
|
||||
decl->name = nullptr;
|
||||
decl->list.vars = *list_move;
|
||||
scc_vec_init(*list_move);
|
||||
}
|
||||
|
||||
// name and var_init can be null
|
||||
// name and var_init can be nullptr
|
||||
static inline void scc_ast_decl_unsafe_val_init(scc_ast_decl_t *decl,
|
||||
scc_ast_type_t *type,
|
||||
const char *name,
|
||||
scc_ast_expr_t *var_init,
|
||||
scc_pos_t loc) {
|
||||
Assert(decl != null && type != null);
|
||||
Assert(decl != nullptr && type != nullptr);
|
||||
decl->base.loc = loc;
|
||||
decl->base.type = SCC_AST_DECL_VAR;
|
||||
decl->name = name;
|
||||
@@ -44,12 +44,12 @@ static inline void scc_ast_decl_unsafe_val_init(scc_ast_decl_t *decl,
|
||||
decl->var.init = var_init;
|
||||
}
|
||||
|
||||
// var_init can be null
|
||||
// var_init can be nullptr
|
||||
static inline void scc_ast_decl_val_init(scc_ast_decl_t *decl,
|
||||
scc_ast_type_t *type, const char *name,
|
||||
scc_ast_expr_t *var_init,
|
||||
scc_pos_t loc) {
|
||||
Assert(decl != null && name != null && type != null);
|
||||
Assert(decl != nullptr && name != nullptr && type != nullptr);
|
||||
decl->base.loc = loc;
|
||||
decl->base.type = SCC_AST_DECL_VAR;
|
||||
decl->name = name;
|
||||
@@ -57,12 +57,12 @@ static inline void scc_ast_decl_val_init(scc_ast_decl_t *decl,
|
||||
decl->var.init = var_init;
|
||||
}
|
||||
|
||||
// body can be null
|
||||
// body can be nullptr
|
||||
static inline void scc_ast_decl_func_init(scc_ast_decl_t *decl,
|
||||
scc_ast_type_t *type,
|
||||
const char *name,
|
||||
scc_ast_stmt_t *body, scc_pos_t loc) {
|
||||
Assert(decl != null && name != null && type != null);
|
||||
Assert(decl != nullptr && name != nullptr && type != nullptr);
|
||||
decl->base.loc = loc;
|
||||
decl->base.type = SCC_AST_DECL_FUNC;
|
||||
decl->name = name;
|
||||
@@ -71,11 +71,11 @@ static inline void scc_ast_decl_func_init(scc_ast_decl_t *decl,
|
||||
decl->func.body = body;
|
||||
}
|
||||
|
||||
// name can be null
|
||||
// name can be nullptr
|
||||
static inline void scc_ast_decl_param_init(scc_ast_decl_t *decl,
|
||||
scc_ast_type_t *type,
|
||||
const char *name, scc_pos_t loc) {
|
||||
Assert(decl != null && type != null);
|
||||
Assert(decl != nullptr && type != nullptr);
|
||||
decl->base.loc = loc;
|
||||
decl->base.type = SCC_AST_DECL_PARAM;
|
||||
decl->name = name;
|
||||
@@ -87,11 +87,11 @@ static inline void _scc_ast_decl_record_init(scc_ast_decl_t *decl,
|
||||
const char *name,
|
||||
scc_ast_decl_vec_t *fields_move,
|
||||
scc_pos_t loc) {
|
||||
Assert(decl != null);
|
||||
Assert(decl != nullptr);
|
||||
decl->base.loc = loc;
|
||||
decl->base.type = type;
|
||||
decl->name = name;
|
||||
if (fields_move == null) {
|
||||
if (fields_move == nullptr) {
|
||||
scc_vec_init(decl->record.fields);
|
||||
} else {
|
||||
decl->record.fields = *fields_move;
|
||||
@@ -99,7 +99,7 @@ static inline void _scc_ast_decl_record_init(scc_ast_decl_t *decl,
|
||||
}
|
||||
}
|
||||
|
||||
// name and fields can be null
|
||||
// name and fields can be nullptr
|
||||
static inline void scc_ast_decl_struct_init(scc_ast_decl_t *decl,
|
||||
const char *name,
|
||||
scc_ast_decl_vec_t *fields_move,
|
||||
@@ -108,7 +108,7 @@ static inline void scc_ast_decl_struct_init(scc_ast_decl_t *decl,
|
||||
loc);
|
||||
}
|
||||
|
||||
// name and fields can be null
|
||||
// name and fields can be nullptr
|
||||
static inline void scc_ast_decl_union_init(scc_ast_decl_t *decl,
|
||||
const char *name,
|
||||
scc_ast_decl_vec_t *fields_move,
|
||||
@@ -116,7 +116,7 @@ static inline void scc_ast_decl_union_init(scc_ast_decl_t *decl,
|
||||
_scc_ast_decl_record_init(decl, SCC_AST_DECL_UNION, name, fields_move, loc);
|
||||
}
|
||||
|
||||
// name and fields can be null
|
||||
// name and fields can be nullptr
|
||||
static inline void scc_ast_decl_enum_init(scc_ast_decl_t *decl,
|
||||
const char *name,
|
||||
scc_ast_decl_vec_t *fields_move,
|
||||
@@ -128,20 +128,20 @@ static inline void scc_ast_decl_typedef_init(scc_ast_decl_t *decl,
|
||||
const char *name,
|
||||
scc_ast_type_t *type,
|
||||
scc_pos_t loc) {
|
||||
Assert(decl != null && name != null && type != null);
|
||||
Assert(decl != nullptr && name != nullptr && type != nullptr);
|
||||
decl->base.loc = loc;
|
||||
decl->base.type = SCC_AST_DECL_TYPEDEF;
|
||||
decl->name = name;
|
||||
decl->typedef_decl.type = type;
|
||||
}
|
||||
|
||||
// items can be null
|
||||
// items can be nullptr
|
||||
static inline void scc_ast_stmt_compound_init(
|
||||
scc_ast_stmt_t *stmt, scc_ast_block_item_vec_t *items_move, scc_pos_t loc) {
|
||||
Assert(stmt != null);
|
||||
Assert(stmt != nullptr);
|
||||
stmt->base.loc = loc;
|
||||
stmt->base.type = SCC_AST_STMT_COMPOUND;
|
||||
if (items_move == null) {
|
||||
if (items_move == nullptr) {
|
||||
scc_vec_init(stmt->compound.block_items);
|
||||
} else {
|
||||
stmt->compound.block_items = *items_move;
|
||||
@@ -149,22 +149,22 @@ static inline void scc_ast_stmt_compound_init(
|
||||
}
|
||||
}
|
||||
|
||||
// expr can be null
|
||||
// expr can be nullptr
|
||||
static inline void scc_ast_stmt_expr_init(scc_ast_stmt_t *stmt,
|
||||
scc_ast_expr_t *expr, scc_pos_t loc) {
|
||||
Assert(stmt != null);
|
||||
Assert(stmt != nullptr);
|
||||
stmt->base.loc = loc;
|
||||
stmt->base.type = SCC_AST_STMT_EXPR;
|
||||
stmt->expr.expr = expr;
|
||||
}
|
||||
|
||||
// opt_else can be null
|
||||
// opt_else can be nullptr
|
||||
static inline void scc_ast_stmt_if_init(scc_ast_stmt_t *stmt,
|
||||
scc_ast_expr_t *cond,
|
||||
scc_ast_stmt_t *then,
|
||||
scc_ast_stmt_t *opt_else,
|
||||
scc_pos_t loc) {
|
||||
Assert(stmt != null && cond != null && then != null);
|
||||
Assert(stmt != nullptr && cond != nullptr && then != nullptr);
|
||||
stmt->base.loc = loc;
|
||||
stmt->base.type = SCC_AST_STMT_IF;
|
||||
stmt->if_stmt.cond = cond;
|
||||
@@ -176,7 +176,7 @@ static inline void scc_ast_stmt_while_init(scc_ast_stmt_t *stmt,
|
||||
scc_ast_expr_t *cond,
|
||||
scc_ast_stmt_t *body,
|
||||
scc_pos_t loc) {
|
||||
Assert(stmt != null && cond != null && body != null);
|
||||
Assert(stmt != nullptr && cond != nullptr && body != nullptr);
|
||||
stmt->base.loc = loc;
|
||||
stmt->base.type = SCC_AST_STMT_WHILE;
|
||||
stmt->while_stmt.cond = cond;
|
||||
@@ -187,7 +187,7 @@ static inline void scc_ast_stmt_do_while_init(scc_ast_stmt_t *stmt,
|
||||
scc_ast_expr_t *cond,
|
||||
scc_ast_stmt_t *body,
|
||||
scc_pos_t loc) {
|
||||
Assert(stmt != null && cond != null && body != null);
|
||||
Assert(stmt != nullptr && cond != nullptr && body != nullptr);
|
||||
stmt->base.loc = loc;
|
||||
stmt->base.type = SCC_AST_STMT_DO_WHILE;
|
||||
stmt->while_stmt.cond = cond;
|
||||
@@ -200,7 +200,7 @@ static inline void scc_ast_stmt_for_init(scc_ast_stmt_t *stmt,
|
||||
scc_ast_expr_t *cond,
|
||||
scc_ast_expr_t *incr,
|
||||
scc_ast_stmt_t *body, scc_pos_t loc) {
|
||||
Assert(stmt != null && body != null);
|
||||
Assert(stmt != nullptr && body != nullptr);
|
||||
stmt->base.loc = loc;
|
||||
stmt->base.type = SCC_AST_STMT_FOR;
|
||||
stmt->for_stmt.init = init;
|
||||
@@ -213,7 +213,7 @@ static inline void scc_ast_stmt_switch_init(scc_ast_stmt_t *stmt,
|
||||
scc_ast_expr_t *cond,
|
||||
scc_ast_stmt_t *body,
|
||||
scc_pos_t loc) {
|
||||
Assert(stmt != null && cond != null && body != null);
|
||||
Assert(stmt != nullptr && cond != nullptr && body != nullptr);
|
||||
stmt->base.loc = loc;
|
||||
stmt->base.type = SCC_AST_STMT_SWITCH;
|
||||
stmt->switch_stmt.cond = cond;
|
||||
@@ -223,7 +223,7 @@ static inline void scc_ast_stmt_switch_init(scc_ast_stmt_t *stmt,
|
||||
static inline void scc_ast_stmt_case_init(scc_ast_stmt_t *stmt,
|
||||
scc_ast_expr_t *cond,
|
||||
scc_ast_stmt_t *body, scc_pos_t loc) {
|
||||
Assert(stmt != null && cond != null && body != null);
|
||||
Assert(stmt != nullptr && cond != nullptr && body != nullptr);
|
||||
stmt->base.loc = loc;
|
||||
stmt->base.type = SCC_AST_STMT_CASE;
|
||||
stmt->case_stmt.expr = cond;
|
||||
@@ -233,7 +233,7 @@ static inline void scc_ast_stmt_case_init(scc_ast_stmt_t *stmt,
|
||||
static inline void scc_ast_stmt_default_init(scc_ast_stmt_t *stmt,
|
||||
scc_ast_stmt_t *body,
|
||||
scc_pos_t loc) {
|
||||
Assert(stmt != null && body != null);
|
||||
Assert(stmt != nullptr && body != nullptr);
|
||||
stmt->base.loc = loc;
|
||||
stmt->base.type = SCC_AST_STMT_DEFAULT;
|
||||
stmt->default_stmt.stmt = body;
|
||||
@@ -241,25 +241,25 @@ static inline void scc_ast_stmt_default_init(scc_ast_stmt_t *stmt,
|
||||
|
||||
static inline void scc_ast_stmt_break_init(scc_ast_stmt_t *stmt,
|
||||
scc_pos_t loc) {
|
||||
Assert(stmt != null);
|
||||
Assert(stmt != nullptr);
|
||||
stmt->base.loc = loc;
|
||||
stmt->base.type = SCC_AST_STMT_BREAK;
|
||||
stmt->jump._target = null;
|
||||
stmt->jump._target = nullptr;
|
||||
}
|
||||
|
||||
static inline void scc_ast_stmt_continue_init(scc_ast_stmt_t *stmt,
|
||||
scc_pos_t loc) {
|
||||
Assert(stmt != null);
|
||||
Assert(stmt != nullptr);
|
||||
stmt->base.loc = loc;
|
||||
stmt->base.type = SCC_AST_STMT_CONTINUE;
|
||||
stmt->jump._target = null;
|
||||
stmt->jump._target = nullptr;
|
||||
}
|
||||
|
||||
// expr can be null
|
||||
// expr can be nullptr
|
||||
static inline void scc_ast_stmt_return_init(scc_ast_stmt_t *stmt,
|
||||
scc_ast_expr_t *expr,
|
||||
scc_pos_t loc) {
|
||||
Assert(stmt != null);
|
||||
Assert(stmt != nullptr);
|
||||
stmt->base.loc = loc;
|
||||
stmt->base.type = SCC_AST_STMT_RETURN;
|
||||
stmt->return_stmt.expr = expr;
|
||||
@@ -267,18 +267,18 @@ static inline void scc_ast_stmt_return_init(scc_ast_stmt_t *stmt,
|
||||
|
||||
static inline void scc_ast_stmt_goto_init(scc_ast_stmt_t *stmt,
|
||||
const char *label, scc_pos_t loc) {
|
||||
Assert(stmt != null && label != null);
|
||||
Assert(stmt != nullptr && label != nullptr);
|
||||
stmt->base.loc = loc;
|
||||
stmt->base.type = SCC_AST_STMT_GOTO;
|
||||
stmt->goto_stmt.label = label;
|
||||
stmt->goto_stmt._target = null;
|
||||
stmt->goto_stmt._target = nullptr;
|
||||
}
|
||||
|
||||
static inline void scc_ast_stmt_label_init(scc_ast_stmt_t *stmt,
|
||||
const char *label,
|
||||
scc_ast_stmt_t *body,
|
||||
scc_pos_t loc) {
|
||||
Assert(stmt != null);
|
||||
Assert(stmt != nullptr);
|
||||
stmt->base.loc = loc;
|
||||
stmt->base.type = SCC_AST_STMT_LABEL;
|
||||
stmt->label_stmt.label = label;
|
||||
@@ -290,7 +290,7 @@ static inline void scc_ast_expr_binary_init(scc_ast_expr_t *expr,
|
||||
scc_ast_expr_t *lhs,
|
||||
scc_ast_expr_t *rhs,
|
||||
scc_pos_t loc) {
|
||||
Assert(expr != null && lhs != null && rhs != null);
|
||||
Assert(expr != nullptr && lhs != nullptr && rhs != nullptr);
|
||||
expr->base.loc = loc;
|
||||
expr->base.type = SCC_AST_EXPR_BINARY;
|
||||
expr->binary.op = op;
|
||||
@@ -302,7 +302,7 @@ static inline void scc_ast_expr_unary_init(scc_ast_expr_t *expr,
|
||||
scc_ast_expr_op_t op,
|
||||
scc_ast_expr_t *operand,
|
||||
scc_pos_t loc) {
|
||||
Assert(expr != null && operand != null);
|
||||
Assert(expr != nullptr && operand != nullptr);
|
||||
expr->base.loc = loc;
|
||||
expr->base.type = SCC_AST_EXPR_UNARY;
|
||||
expr->unary.op = op;
|
||||
@@ -314,8 +314,8 @@ static inline void scc_ast_expr_cond_init(scc_ast_expr_t *expr,
|
||||
scc_ast_expr_t *then_expr,
|
||||
scc_ast_expr_t *else_expr,
|
||||
scc_pos_t loc) {
|
||||
Assert(expr != null && cond != null && then_expr != null &&
|
||||
else_expr != null);
|
||||
Assert(expr != nullptr && cond != nullptr && then_expr != nullptr &&
|
||||
else_expr != nullptr);
|
||||
expr->base.loc = loc;
|
||||
expr->base.type = SCC_AST_EXPR_COND;
|
||||
expr->cond.cond = cond;
|
||||
@@ -323,16 +323,16 @@ static inline void scc_ast_expr_cond_init(scc_ast_expr_t *expr,
|
||||
expr->cond.else_expr = else_expr;
|
||||
}
|
||||
|
||||
// args can be null
|
||||
// args can be nullptr
|
||||
static inline void scc_ast_expr_call_init(scc_ast_expr_t *expr,
|
||||
scc_ast_expr_t *callee,
|
||||
scc_ast_expr_vec_t *args,
|
||||
scc_pos_t loc) {
|
||||
Assert(expr != null && callee != null);
|
||||
Assert(expr != nullptr && callee != nullptr);
|
||||
expr->base.loc = loc;
|
||||
expr->base.type = SCC_AST_EXPR_CALL;
|
||||
expr->call.callee = callee;
|
||||
if (args == null) {
|
||||
if (args == nullptr) {
|
||||
scc_vec_init(expr->call.args);
|
||||
} else {
|
||||
expr->call.args = *args;
|
||||
@@ -344,7 +344,7 @@ static inline void scc_ast_expr_array_subscript_init(scc_ast_expr_t *expr,
|
||||
scc_ast_expr_t *array,
|
||||
scc_ast_expr_t *index,
|
||||
scc_pos_t loc) {
|
||||
Assert(expr != null && array != null && index != null);
|
||||
Assert(expr != nullptr && array != nullptr && index != nullptr);
|
||||
expr->base.loc = loc;
|
||||
expr->base.type = SCC_AST_EXPR_ARRAY_SUBSCRIPT;
|
||||
expr->subscript.array = array;
|
||||
@@ -356,7 +356,7 @@ static inline void _scc_ast_expr_member_init(scc_ast_expr_t *expr,
|
||||
scc_ast_expr_t *object,
|
||||
const char *member,
|
||||
scc_pos_t loc) {
|
||||
Assert(expr != null && object != null && member != null);
|
||||
Assert(expr != nullptr && object != nullptr && member != nullptr);
|
||||
expr->base.loc = loc;
|
||||
expr->base.type = type;
|
||||
expr->member.base = object;
|
||||
@@ -382,31 +382,31 @@ static inline void scc_ast_expr_cast_init(scc_ast_expr_t *expr,
|
||||
scc_ast_type_t *type,
|
||||
scc_ast_expr_t *operand,
|
||||
scc_pos_t loc) {
|
||||
Assert(expr != null && type != null && operand != null);
|
||||
Assert(expr != nullptr && type != nullptr && operand != nullptr);
|
||||
expr->base.loc = loc;
|
||||
expr->base.type = SCC_AST_EXPR_CAST;
|
||||
expr->cast.type = type;
|
||||
expr->cast.expr = operand;
|
||||
}
|
||||
|
||||
// type and target_expr can be null but it only one of them can be null
|
||||
// type and target_expr can be nullptr but it only one of them can be nullptr
|
||||
static inline void scc_ast_expr_sizeof_init(scc_ast_expr_t *expr,
|
||||
scc_ast_type_t *type,
|
||||
scc_ast_expr_t *target_expr,
|
||||
scc_pos_t loc) {
|
||||
Assert(expr != null);
|
||||
Assert(expr != nullptr);
|
||||
expr->base.loc = loc;
|
||||
expr->base.type = SCC_AST_EXPR_SIZE_OF;
|
||||
expr->attr_of.type = type;
|
||||
expr->attr_of.expr = target_expr;
|
||||
}
|
||||
|
||||
// type and target_expr can be null but it only one of them can be null
|
||||
// type and target_expr can be nullptr but it only one of them can be nullptr
|
||||
static inline void scc_ast_expr_alignof_init(scc_ast_expr_t *expr,
|
||||
scc_ast_type_t *type,
|
||||
scc_ast_expr_t *target_expr,
|
||||
scc_pos_t loc) {
|
||||
Assert(expr != null);
|
||||
Assert(expr != nullptr);
|
||||
expr->base.loc = loc;
|
||||
expr->base.type =
|
||||
SCC_AST_EXPR_SIZE_OF; // 注意:这里使用了 SIZE_OF,可能需要改为 ALIGN_OF
|
||||
@@ -414,25 +414,25 @@ static inline void scc_ast_expr_alignof_init(scc_ast_expr_t *expr,
|
||||
expr->attr_of.expr = target_expr;
|
||||
}
|
||||
|
||||
// lhs_exprs and rhs_exprs can be null
|
||||
// lhs_exprs and rhs_exprs can be nullptr
|
||||
static inline void scc_ast_expr_compound_init(scc_ast_expr_t *expr,
|
||||
scc_ast_expr_t *base,
|
||||
scc_ast_expr_vec_t *lhs_exprs,
|
||||
scc_ast_expr_vec_t *rhs_exprs,
|
||||
scc_pos_t loc) {
|
||||
Assert(expr != null && base != null);
|
||||
Assert(expr != nullptr && base != nullptr);
|
||||
expr->base.loc = loc;
|
||||
expr->base.type = SCC_AST_EXPR_COMPOUND;
|
||||
expr->compound.base = base;
|
||||
|
||||
if (lhs_exprs == null) {
|
||||
if (lhs_exprs == nullptr) {
|
||||
scc_vec_init(expr->compound.lhs_exprs);
|
||||
} else {
|
||||
expr->compound.lhs_exprs = *lhs_exprs;
|
||||
scc_vec_init(*lhs_exprs);
|
||||
}
|
||||
|
||||
if (rhs_exprs == null) {
|
||||
if (rhs_exprs == nullptr) {
|
||||
scc_vec_init(expr->compound.rhs_exprs);
|
||||
} else {
|
||||
expr->compound.rhs_exprs = *rhs_exprs;
|
||||
@@ -444,7 +444,7 @@ static inline void scc_ast_expr_literal_init(scc_ast_expr_t *expr,
|
||||
scc_ast_node_type_t type,
|
||||
const char *value, cbool owned,
|
||||
scc_pos_t loc) {
|
||||
Assert(expr != null && value != null);
|
||||
Assert(expr != nullptr && value != nullptr);
|
||||
expr->base.loc = loc;
|
||||
expr->base.type = type;
|
||||
expr->literal.lexme = value;
|
||||
@@ -481,17 +481,17 @@ static inline void scc_ast_expr_literal_string_init(scc_ast_expr_t *expr,
|
||||
static inline void scc_ast_expr_identifier_init(scc_ast_expr_t *expr,
|
||||
const char *name,
|
||||
scc_pos_t loc) {
|
||||
Assert(expr != null && name != null);
|
||||
Assert(expr != nullptr && name != nullptr);
|
||||
expr->base.loc = loc;
|
||||
expr->base.type = SCC_AST_EXPR_IDENTIFIER;
|
||||
expr->identifier.name = name;
|
||||
expr->identifier._target = null;
|
||||
expr->identifier._target = nullptr;
|
||||
}
|
||||
|
||||
static inline void scc_ast_expr_lvalue_init(scc_ast_expr_t *expr,
|
||||
scc_ast_type_t *type,
|
||||
scc_pos_t loc) {
|
||||
Assert(expr != null && type != null);
|
||||
Assert(expr != nullptr && type != nullptr);
|
||||
expr->base.loc = loc;
|
||||
expr->base.type = SCC_AST_EXPR_LVALUE;
|
||||
expr->lvalue.type = type;
|
||||
@@ -501,7 +501,7 @@ static inline void scc_ast_expr_lvalue_init(scc_ast_expr_t *expr,
|
||||
static inline void scc_ast_type_builtin_init(scc_ast_type_t *type,
|
||||
scc_ast_builtin_type_t builtin,
|
||||
scc_pos_t loc) {
|
||||
Assert(type != null);
|
||||
Assert(type != nullptr);
|
||||
type->base.loc = loc;
|
||||
type->base.type = SCC_AST_TYPE_BUILTIN;
|
||||
type->builtin.type = builtin;
|
||||
@@ -511,19 +511,19 @@ static inline void scc_ast_type_builtin_init(scc_ast_type_t *type,
|
||||
static inline void scc_ast_type_pointer_init(scc_ast_type_t *type,
|
||||
scc_ast_type_t *pointee,
|
||||
scc_pos_t loc) {
|
||||
Assert(type != null && pointee != null);
|
||||
Assert(type != nullptr && pointee != nullptr);
|
||||
type->base.loc = loc;
|
||||
type->base.type = SCC_AST_TYPE_POINTER;
|
||||
type->quals = (scc_ast_decl_specifier_t){0}; // FIXME
|
||||
type->pointer.pointee = pointee;
|
||||
}
|
||||
|
||||
// size can be null
|
||||
// size can be nullptr
|
||||
static inline void scc_ast_type_array_init(scc_ast_type_t *type,
|
||||
scc_ast_type_t *element,
|
||||
scc_ast_expr_t *size,
|
||||
scc_pos_t loc) {
|
||||
Assert(type != null && element != null);
|
||||
Assert(type != nullptr && element != nullptr);
|
||||
type->base.loc = loc;
|
||||
type->base.type = SCC_AST_TYPE_ARRAY;
|
||||
type->quals = (scc_ast_decl_specifier_t){0}; // FIXME
|
||||
@@ -531,17 +531,17 @@ static inline void scc_ast_type_array_init(scc_ast_type_t *type,
|
||||
type->array.size = size;
|
||||
}
|
||||
|
||||
// return_type and params can be null
|
||||
// return_type and params can be nullptr
|
||||
static inline void scc_ast_type_function_init(scc_ast_type_t *type,
|
||||
scc_ast_type_t *return_type,
|
||||
scc_ast_decl_vec_t *params,
|
||||
scc_pos_t loc) {
|
||||
Assert(type != null);
|
||||
Assert(type != nullptr);
|
||||
type->base.loc = loc;
|
||||
type->base.type = SCC_AST_TYPE_FUNCTION;
|
||||
type->function.return_type = return_type;
|
||||
type->quals = (scc_ast_decl_specifier_t){0}; // FIXME
|
||||
if (params == null) {
|
||||
if (params == nullptr) {
|
||||
scc_vec_init(type->function.params);
|
||||
} else {
|
||||
type->function.params = *params;
|
||||
@@ -554,7 +554,7 @@ static inline void _scc_ast_type_record_init(scc_ast_type_t *type,
|
||||
const char *name,
|
||||
scc_ast_decl_t *decl,
|
||||
scc_pos_t loc) {
|
||||
Assert(type != null);
|
||||
Assert(type != nullptr);
|
||||
type->base.loc = loc;
|
||||
type->base.type = type_kind;
|
||||
type->quals = (scc_ast_decl_specifier_t){0}; // FIXME
|
||||
@@ -562,7 +562,7 @@ static inline void _scc_ast_type_record_init(scc_ast_type_t *type,
|
||||
type->record.decl = decl;
|
||||
}
|
||||
|
||||
// name and decl can be null
|
||||
// name and decl can be nullptr
|
||||
static inline void scc_ast_type_struct_init(scc_ast_type_t *type,
|
||||
const char *name,
|
||||
scc_ast_decl_t *decl,
|
||||
@@ -570,7 +570,7 @@ static inline void scc_ast_type_struct_init(scc_ast_type_t *type,
|
||||
_scc_ast_type_record_init(type, SCC_AST_TYPE_STRUCT, name, decl, loc);
|
||||
}
|
||||
|
||||
// name and decl can be null
|
||||
// name and decl can be nullptr
|
||||
static inline void scc_ast_type_union_init(scc_ast_type_t *type,
|
||||
const char *name,
|
||||
scc_ast_decl_t *decl,
|
||||
@@ -578,7 +578,7 @@ static inline void scc_ast_type_union_init(scc_ast_type_t *type,
|
||||
_scc_ast_type_record_init(type, SCC_AST_TYPE_UNION, name, decl, loc);
|
||||
}
|
||||
|
||||
// name and decl can be null
|
||||
// name and decl can be nullptr
|
||||
static inline void scc_ast_type_enum_init(scc_ast_type_t *type,
|
||||
const char *name,
|
||||
scc_ast_decl_t *decl, scc_pos_t loc) {
|
||||
@@ -589,7 +589,7 @@ static inline void scc_ast_type_typedef_init(scc_ast_type_t *type,
|
||||
const char *name,
|
||||
scc_ast_decl_t *target,
|
||||
scc_pos_t loc) {
|
||||
Assert(type != null && target != null);
|
||||
Assert(type != nullptr && target != nullptr);
|
||||
type->base.loc = loc;
|
||||
type->base.type = SCC_AST_TYPE_TYPEDEF;
|
||||
type->quals = (scc_ast_decl_specifier_t){0}; // FIXME
|
||||
|
||||
@@ -269,7 +269,7 @@ static void dump_type_impl(scc_ast_type_t *type, scc_tree_dump_t *td) {
|
||||
break;
|
||||
case SCC_AST_TYPE_ARRAY:
|
||||
dump_child_node(td, (scc_ast_node_t *)type->array.element,
|
||||
type->array.size == NULL);
|
||||
type->array.size == nullptr);
|
||||
if (type->array.size)
|
||||
dump_child_node(td, (scc_ast_node_t *)type->array.size, true);
|
||||
break;
|
||||
@@ -499,7 +499,7 @@ static void dump_decl_impl(scc_ast_decl_t *decl, scc_tree_dump_t *td) {
|
||||
case SCC_AST_DECL_VAR:
|
||||
if (decl->var.type) {
|
||||
dump_child_node(td, (scc_ast_node_t *)decl->var.type,
|
||||
decl->var.init == NULL);
|
||||
decl->var.init == nullptr);
|
||||
if (decl->var.init)
|
||||
dump_child_node(td, (scc_ast_node_t *)decl->var.init, true);
|
||||
}
|
||||
@@ -507,7 +507,7 @@ static void dump_decl_impl(scc_ast_decl_t *decl, scc_tree_dump_t *td) {
|
||||
case SCC_AST_DECL_FUNC:
|
||||
if (decl->func.type) {
|
||||
dump_child_node(td, (scc_ast_node_t *)decl->func.type,
|
||||
decl->func.body == NULL);
|
||||
decl->func.body == nullptr);
|
||||
if (decl->func.body)
|
||||
dump_child_node(td, (scc_ast_node_t *)decl->func.body, true);
|
||||
}
|
||||
|
||||
@@ -130,7 +130,7 @@ static const scc_type_abi_t scc_win_x64_type_abi[] = {
|
||||
.alignment = 8,
|
||||
},
|
||||
{
|
||||
// NULL
|
||||
// nullptr
|
||||
.ast_type = SCC_AST_BUILTIN_TYPE_UNKNOWN,
|
||||
.ir_type = SCC_IR_TYPE_unknown,
|
||||
.size = 0,
|
||||
|
||||
@@ -12,8 +12,8 @@ static inline void parse_lexme2const_int(const char *lexme,
|
||||
|
||||
scc_ir_type_ref_t scc_ast2ir_type(scc_ast2ir_ctx_t *ctx,
|
||||
scc_ast_type_t *ast_type) {
|
||||
if (ctx == null || ast_type == null) {
|
||||
LOG_ERROR("args is null");
|
||||
if (ctx == nullptr || ast_type == nullptr) {
|
||||
LOG_ERROR("args is nullptr");
|
||||
return 0;
|
||||
}
|
||||
scc_ir_type_t ir_type;
|
||||
@@ -42,17 +42,13 @@ scc_ir_type_ref_t scc_ast2ir_type(scc_ast2ir_ctx_t *ctx,
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
case SCC_AST_TYPE_POINTER: {
|
||||
scc_ir_type_init(&ir_type, SCC_IR_TYPE_PTR);
|
||||
|
||||
scc_ir_type_ref_t pointee_type =
|
||||
scc_ast2ir_type(ctx, ast_type->pointer.pointee);
|
||||
|
||||
ir_type.data.pointer.base = pointee_type;
|
||||
break;
|
||||
}
|
||||
|
||||
case SCC_AST_TYPE_ARRAY: {
|
||||
scc_ir_type_init(&ir_type, SCC_IR_TYPE_ARRAY);
|
||||
|
||||
@@ -60,7 +56,6 @@ scc_ir_type_ref_t scc_ast2ir_type(scc_ast2ir_ctx_t *ctx,
|
||||
scc_ast2ir_type(ctx, ast_type->array.element);
|
||||
|
||||
ir_type.data.array.base = element_type;
|
||||
// TODO: 处理数组大小表达式
|
||||
ir_type.data.array.len = 0;
|
||||
if (ast_type->array.size) {
|
||||
// TODO constant expression
|
||||
@@ -73,7 +68,6 @@ scc_ir_type_ref_t scc_ast2ir_type(scc_ast2ir_ctx_t *ctx,
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
case SCC_AST_TYPE_FUNCTION: {
|
||||
scc_ir_type_init(&ir_type, SCC_IR_TYPE_FUNC);
|
||||
|
||||
@@ -98,13 +92,11 @@ scc_ir_type_ref_t scc_ast2ir_type(scc_ast2ir_ctx_t *ctx,
|
||||
ir_type.data.function.params = params;
|
||||
break;
|
||||
}
|
||||
|
||||
// SCC_AST_TYPE_STRUCT, // 结构体类型
|
||||
// SCC_AST_TYPE_UNION, // 联合类型
|
||||
// SCC_AST_TYPE_ENUM, // 枚举类型
|
||||
case SCC_AST_TYPE_TYPEDEF:
|
||||
break;
|
||||
|
||||
default:
|
||||
LOG_FATAL("Unsupported AST type: %d", ast_type->base.type);
|
||||
return 0;
|
||||
@@ -207,8 +199,8 @@ scc_ir_value_ref_t scc_ast2ir_logical_expr(scc_ast2ir_ctx_t *ctx,
|
||||
*/
|
||||
scc_ir_value_ref_t scc_ast2ir_expr(scc_ast2ir_ctx_t *ctx, scc_ast_expr_t *expr,
|
||||
cbool is_lvalue) {
|
||||
if (ctx == null || expr == null) {
|
||||
LOG_ERROR("args is null");
|
||||
if (ctx == nullptr || expr == nullptr) {
|
||||
LOG_ERROR("args is nullptr");
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -332,7 +324,6 @@ scc_ir_value_ref_t scc_ast2ir_expr(scc_ast2ir_ctx_t *ctx, scc_ast_expr_t *expr,
|
||||
// 创建操作节点
|
||||
return scc_ir_builder_binop(&ctx->builder, op, lhs, rhs);
|
||||
}
|
||||
|
||||
case SCC_AST_EXPR_UNARY: {
|
||||
if (expr->unary.op == SCC_AST_OP_ADDRESS_OF) {
|
||||
return scc_ast2ir_expr(ctx, expr->unary.operand, true);
|
||||
@@ -399,13 +390,13 @@ scc_ir_value_ref_t scc_ast2ir_expr(scc_ast2ir_ctx_t *ctx, scc_ast_expr_t *expr,
|
||||
LOG_FATAL("Unsupported unary operator: %d", expr->unary.op);
|
||||
return 0;
|
||||
}
|
||||
UNREACHABLE();
|
||||
break;
|
||||
}
|
||||
|
||||
case SCC_AST_EXPR_COND: {
|
||||
TODO();
|
||||
break;
|
||||
}
|
||||
|
||||
case SCC_AST_EXPR_CALL: {
|
||||
// 转换参数
|
||||
scc_ir_node_ref_vec_t args;
|
||||
@@ -430,7 +421,6 @@ scc_ir_value_ref_t scc_ast2ir_expr(scc_ast2ir_ctx_t *ctx, scc_ast_expr_t *expr,
|
||||
scc_vec_free(args);
|
||||
return node;
|
||||
}
|
||||
|
||||
// SCC_AST_EXPR_ARRAY_SUBSCRIPT, // 数组下标
|
||||
// SCC_AST_EXPR_MEMBER, // 成员访问 .
|
||||
// SCC_AST_EXPR_PTR_MEMBER, // 指针成员访问 ->
|
||||
@@ -440,7 +430,6 @@ scc_ir_value_ref_t scc_ast2ir_expr(scc_ast2ir_ctx_t *ctx, scc_ast_expr_t *expr,
|
||||
// SCC_AST_EXPR_COMPOUND, // 复合字面量
|
||||
// SCC_AST_EXPR_LVALUE, // 右值
|
||||
// SCC_AST_EXPR_BUILTIN,// 内置表达式 ... directive map to ir builtin
|
||||
|
||||
case SCC_AST_EXPR_INT_LITERAL: {
|
||||
// FIXME maybe using some array to int;
|
||||
scc_ir_type_ref_t type_ref = scc_ir_builder_type_i32(&ctx->builder);
|
||||
@@ -487,9 +476,8 @@ scc_ir_value_ref_t scc_ast2ir_expr(scc_ast2ir_ctx_t *ctx, scc_ast_expr_t *expr,
|
||||
TODO();
|
||||
break;
|
||||
}
|
||||
|
||||
case SCC_AST_EXPR_IDENTIFIER: {
|
||||
if (expr->identifier._target == null) {
|
||||
if (expr->identifier._target == nullptr) {
|
||||
LOG_ERROR("unknown identifier %s", expr->identifier.name);
|
||||
}
|
||||
// FIXME hack hashtable
|
||||
@@ -499,7 +487,20 @@ scc_ir_value_ref_t scc_ast2ir_expr(scc_ast2ir_ctx_t *ctx, scc_ast_expr_t *expr,
|
||||
if (is_lvalue) {
|
||||
return in;
|
||||
} else {
|
||||
return scc_ir_builder_load(&ctx->builder, in);
|
||||
// 右值:如果是数组类型,退化为指针(返回地址)
|
||||
scc_ir_type_t *ir_type =
|
||||
scc_ir_module_get_type_by_value(ctx->builder.ctx.module, in);
|
||||
Assert(ir_type->tag == SCC_IR_TYPE_PTR);
|
||||
scc_ir_type_t *target_type = scc_ir_module_get_type(
|
||||
ctx->builder.ctx.module, ir_type->data.pointer.base);
|
||||
if (target_type->tag == SCC_IR_TYPE_ARRAY) {
|
||||
// 生成 getptr 获取数组首地址
|
||||
return scc_ir_builder_get_ptr(&ctx->builder, in,
|
||||
SCC_IR_REF_nullptr);
|
||||
} else {
|
||||
// 标量类型:加载值
|
||||
return scc_ir_builder_load(&ctx->builder, in);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -516,7 +517,7 @@ scc_ir_value_ref_t scc_ast2ir_expr(scc_ast2ir_ctx_t *ctx, scc_ast_expr_t *expr,
|
||||
* @param stmt
|
||||
*/
|
||||
void scc_ast2ir_stmt(scc_ast2ir_ctx_t *ctx, scc_ast_stmt_t *stmt) {
|
||||
if (stmt == null) {
|
||||
if (stmt == nullptr) {
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -537,12 +538,10 @@ void scc_ast2ir_stmt(scc_ast2ir_ctx_t *ctx, scc_ast_stmt_t *stmt) {
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
case SCC_AST_STMT_EXPR: {
|
||||
scc_ast2ir_expr(ctx, stmt->expr.expr, false);
|
||||
break;
|
||||
}
|
||||
|
||||
case SCC_AST_STMT_IF: {
|
||||
/*
|
||||
branch cond
|
||||
@@ -580,7 +579,6 @@ void scc_ast2ir_stmt(scc_ast2ir_ctx_t *ctx, scc_ast_stmt_t *stmt) {
|
||||
scc_ir_builder_set_current_bblock(&ctx->builder, merge_block);
|
||||
break;
|
||||
}
|
||||
|
||||
case SCC_AST_STMT_WHILE: {
|
||||
scc_ir_bblock_ref_t cond_block =
|
||||
scc_ir_builder_bblock(&ctx->builder, "while_cond");
|
||||
@@ -603,7 +601,6 @@ void scc_ast2ir_stmt(scc_ast2ir_ctx_t *ctx, scc_ast_stmt_t *stmt) {
|
||||
scc_ir_builder_set_current_bblock(&ctx->builder, exit_block);
|
||||
break;
|
||||
}
|
||||
|
||||
case SCC_AST_STMT_DO_WHILE: {
|
||||
scc_ir_bblock_ref_t cond_block =
|
||||
scc_ir_builder_bblock(&ctx->builder, "do_while_cond");
|
||||
@@ -626,7 +623,6 @@ void scc_ast2ir_stmt(scc_ast2ir_ctx_t *ctx, scc_ast_stmt_t *stmt) {
|
||||
scc_ir_builder_set_current_bblock(&ctx->builder, exit_block);
|
||||
break;
|
||||
}
|
||||
|
||||
case SCC_AST_STMT_FOR: {
|
||||
scc_ir_bblock_ref_t cond_block =
|
||||
scc_ir_builder_bblock(&ctx->builder, "for_while_cond");
|
||||
@@ -670,7 +666,6 @@ void scc_ast2ir_stmt(scc_ast2ir_ctx_t *ctx, scc_ast_stmt_t *stmt) {
|
||||
scc_ir_builder_set_current_bblock(&ctx->builder, exit_block);
|
||||
break;
|
||||
}
|
||||
|
||||
// SCC_AST_STMT_SWITCH, // switch 语句
|
||||
// SCC_AST_STMT_CASE, // case 语句
|
||||
// SCC_AST_STMT_DEFAULT, // default 语句
|
||||
@@ -701,7 +696,7 @@ void scc_ast2ir_stmt(scc_ast2ir_ctx_t *ctx, scc_ast_stmt_t *stmt) {
|
||||
* @param decl
|
||||
*/
|
||||
void scc_ast2ir_decl(scc_ast2ir_ctx_t *ctx, scc_ast_decl_t *decl) {
|
||||
if (ctx == null || decl == null) {
|
||||
if (ctx == nullptr || decl == nullptr) {
|
||||
LOG_ERROR("Invalid argument");
|
||||
return;
|
||||
}
|
||||
@@ -709,11 +704,10 @@ void scc_ast2ir_decl(scc_ast2ir_ctx_t *ctx, scc_ast_decl_t *decl) {
|
||||
switch (decl->base.type) {
|
||||
case SCC_AST_DECL_VAR: {
|
||||
// 转换类型
|
||||
scc_ir_type_ref_t ir_type = scc_ast2ir_type(ctx, decl->var.type);
|
||||
|
||||
scc_ir_type_ref_t ir_type_ref = scc_ast2ir_type(ctx, decl->var.type);
|
||||
// 创建分配节点
|
||||
scc_ir_value_ref_t alloc_val_node =
|
||||
scc_ir_builder_alloca(&ctx->builder, ir_type, decl->name);
|
||||
scc_ir_builder_alloca(&ctx->builder, ir_type_ref, decl->name);
|
||||
|
||||
scc_hashtable_set(&ctx->decl2ir_ref, decl,
|
||||
(void *)(usize)alloc_val_node);
|
||||
@@ -724,10 +718,30 @@ void scc_ast2ir_decl(scc_ast2ir_ctx_t *ctx, scc_ast_decl_t *decl) {
|
||||
}
|
||||
scc_ir_value_ref_t init_val_node =
|
||||
scc_ast2ir_expr(ctx, decl->var.init, false);
|
||||
|
||||
// FIXME array auto calucate size
|
||||
scc_ir_type_t *ir_type =
|
||||
scc_ir_module_get_type(ctx->builder.ctx.module, ir_type_ref);
|
||||
if (ir_type->tag == SCC_IR_TYPE_ARRAY && ir_type->data.array.len == 0) {
|
||||
scc_ast_expr_t *init_expr = decl->var.init;
|
||||
if (init_expr->base.type == SCC_AST_EXPR_COMPOUND) {
|
||||
Panic("TODO: init_expr->base.type == SCC_AST_EXPR_COMPOUND");
|
||||
} else if (init_expr->base.type == SCC_AST_EXPR_STRING_LITERAL) {
|
||||
ir_type->data.array.len =
|
||||
scc_strlen(init_expr->literal.lexme) + 1;
|
||||
|
||||
scc_ir_const_int_t len = {.int64 = ir_type->data.array.len};
|
||||
scc_ir_value_ref_t len_ref = scc_ir_builder_const_int(
|
||||
&ctx->builder, scc_ir_builder_type_u64(&ctx->builder), len);
|
||||
scc_ir_builder_builtin_memcpy(&ctx->builder, alloc_val_node,
|
||||
init_val_node, len_ref);
|
||||
} else {
|
||||
Panic("unknown init expr in array decl");
|
||||
}
|
||||
}
|
||||
scc_ir_builder_store(&ctx->builder, alloc_val_node, init_val_node);
|
||||
break;
|
||||
}
|
||||
|
||||
case SCC_AST_DECL_FUNC: {
|
||||
scc_ir_type_ref_t func_type_ref = scc_ast2ir_type(ctx, decl->func.type);
|
||||
scc_ir_func_ref_t func_ref =
|
||||
@@ -739,15 +753,15 @@ void scc_ast2ir_decl(scc_ast2ir_ctx_t *ctx, scc_ast_decl_t *decl) {
|
||||
(void *)(usize)func_ref);
|
||||
}
|
||||
|
||||
if (decl->func.body == null) {
|
||||
if (decl->func.body == nullptr) {
|
||||
// function decl
|
||||
break;
|
||||
}
|
||||
|
||||
scc_ir_builder_begin_func(&ctx->builder, func_ref, null);
|
||||
scc_ir_builder_begin_func(&ctx->builder, func_ref, nullptr);
|
||||
scc_ir_func_t *func =
|
||||
scc_ir_module_get_func(ctx->builder.ctx.module, func_ref);
|
||||
Assert(func != null);
|
||||
Assert(func != nullptr);
|
||||
scc_ir_builder_begin_bblock(&ctx->builder, "entry");
|
||||
scc_vec_foreach(decl->func.type->function.params, i) {
|
||||
scc_ast_decl_t *param =
|
||||
@@ -756,7 +770,7 @@ void scc_ast2ir_decl(scc_ast2ir_ctx_t *ctx, scc_ast_decl_t *decl) {
|
||||
scc_ir_value_ref_t param_node_ref = scc_vec_at(func->params, i);
|
||||
scc_ir_value_t *param_node = scc_ir_module_get_value(
|
||||
ctx->builder.ctx.module, param_node_ref);
|
||||
Assert(param_node != null);
|
||||
Assert(param_node != nullptr);
|
||||
param_node->name = param->name;
|
||||
scc_hashtable_set(&ctx->decl2ir_ref, param,
|
||||
(void *)(usize)param_node_ref);
|
||||
@@ -769,7 +783,6 @@ void scc_ast2ir_decl(scc_ast2ir_ctx_t *ctx, scc_ast_decl_t *decl) {
|
||||
scc_ir_builder_end_func(&ctx->builder);
|
||||
break;
|
||||
}
|
||||
|
||||
case SCC_AST_DECL_LIST: {
|
||||
scc_vec_foreach(decl->list.vars, i) {
|
||||
scc_ast_decl_t *sub_decl = scc_vec_at(decl->list.vars, i);
|
||||
@@ -784,11 +797,9 @@ void scc_ast2ir_decl(scc_ast2ir_ctx_t *ctx, scc_ast_decl_t *decl) {
|
||||
break;
|
||||
case SCC_AST_DECL_UNION:
|
||||
break;
|
||||
|
||||
case SCC_AST_DECL_ENUM:
|
||||
case SCC_AST_DECL_TYPEDEF:
|
||||
break;
|
||||
|
||||
default:
|
||||
LOG_FATAL("Unsupported declaration type: %d", decl->base.type);
|
||||
break;
|
||||
@@ -797,7 +808,7 @@ void scc_ast2ir_decl(scc_ast2ir_ctx_t *ctx, scc_ast_decl_t *decl) {
|
||||
|
||||
void scc_ast2ir_translation_unit(scc_ast2ir_ctx_t *ctx,
|
||||
scc_ast_translation_unit_t *tu) {
|
||||
Assert(ctx != null && tu != null);
|
||||
Assert(ctx != nullptr && tu != nullptr);
|
||||
|
||||
scc_vec_foreach(tu->declarations, i) {
|
||||
scc_ast_decl_t *decl = scc_vec_at(tu->declarations, i);
|
||||
@@ -812,7 +823,7 @@ static int scc_cmp_node(const void *key1, const void *key2) {
|
||||
|
||||
void scc_ast2ir_ctx_init(scc_ast2ir_ctx_t *ctx, const scc_type_abi_t *abi,
|
||||
scc_ir_cprog_t *cprog) {
|
||||
Assert(ctx != null);
|
||||
Assert(ctx != nullptr);
|
||||
ctx->abi = abi;
|
||||
scc_ir_builder_init(&ctx->builder, cprog);
|
||||
scc_hashtable_init(&ctx->decl2ir_ref, scc_hash_node, scc_cmp_node);
|
||||
|
||||
@@ -68,15 +68,32 @@ SCC_IR_BUILDER_TYPE_FUNC(f32)
|
||||
SCC_IR_BUILDER_TYPE_FUNC(f64)
|
||||
SCC_IR_BUILDER_TYPE_FUNC(f128)
|
||||
|
||||
static inline scc_ir_value_ref_t
|
||||
scc_ir_builder_builtin_memcpy(scc_ir_builder_t *builder,
|
||||
scc_ir_value_ref_t dest, scc_ir_value_ref_t src,
|
||||
scc_ir_value_ref_t len) {
|
||||
scc_ir_value_t value;
|
||||
scc_ir_value_init(&value, nullptr, SCC_IR_VALUE_TAG_BUILTIN);
|
||||
value.type = scc_ir_builder_type_void(builder); // memcpy 返回 void*
|
||||
value.data.builtin.tag = SCC_IR_BUILTIN_TAG_MEMCPY;
|
||||
value.data.builtin.func.memcpy.dest = dest;
|
||||
value.data.builtin.func.memcpy.src = src;
|
||||
value.data.builtin.func.memcpy.size = len;
|
||||
scc_ir_value_ref_t ref =
|
||||
scc_ir_module_add_value(builder->ctx.module, &value);
|
||||
scc_ir_builder_add_instr(builder, ref);
|
||||
return ref;
|
||||
}
|
||||
|
||||
// TODO
|
||||
static inline scc_ir_value_ref_t
|
||||
scc_ir_builder_const_int(scc_ir_builder_t *builder, scc_ir_type_ref_t type,
|
||||
scc_ir_const_int_t value) {
|
||||
scc_ir_value_t node;
|
||||
scc_ir_node_init(&node, null, SCC_IR_VALUE_TAG_CONST_INT);
|
||||
node.data.const_int = value;
|
||||
node.type = type;
|
||||
return scc_ir_module_add_value(&builder->cprog->module, &node);
|
||||
scc_ir_const_int_t val) {
|
||||
scc_ir_value_t value;
|
||||
scc_ir_value_init(&value, nullptr, SCC_IR_VALUE_TAG_CONST_INT);
|
||||
value.data.const_int = val;
|
||||
value.type = type;
|
||||
return scc_ir_module_add_value(&builder->cprog->module, &value);
|
||||
}
|
||||
|
||||
static inline scc_ir_value_ref_t
|
||||
@@ -86,17 +103,11 @@ scc_ir_builder_const_string(scc_ir_builder_t *builder, const char *str,
|
||||
scc_ir_type_t array_type = {
|
||||
.tag = SCC_IR_TYPE_ARRAY,
|
||||
.data.array.base = u8_type,
|
||||
.data.array.len = len - 1, // 包含 null 结尾
|
||||
.data.array.len = len - 1, // 包含 nullptr 结尾
|
||||
};
|
||||
scc_ir_type_ref_t array_type_ref =
|
||||
scc_ir_ctx_get_type(&builder->ctx, &array_type);
|
||||
|
||||
// 2. 创建指针类型:指向 array_type
|
||||
scc_ir_type_t ptr_type = {.tag = SCC_IR_TYPE_PTR,
|
||||
.data.pointer.base = u8_type};
|
||||
scc_ir_type_ref_t ptr_type_ref =
|
||||
scc_ir_ctx_get_type(&builder->ctx, &ptr_type);
|
||||
|
||||
// 5. 创建聚合节点
|
||||
scc_ir_value_t const_array_value = {
|
||||
.tag = SCC_IR_VALUE_TAG_CONST_ARRAY,
|
||||
@@ -111,10 +122,10 @@ scc_ir_builder_const_string(scc_ir_builder_t *builder, const char *str,
|
||||
}
|
||||
buff[len - 2] = '\0';
|
||||
scc_vec_unsafe_from_buffer(const_array_value.data.const_array.elements,
|
||||
buff, len - 1);
|
||||
(u8 *)buff, len - 1);
|
||||
scc_ir_value_ref_t const_array_ref =
|
||||
scc_ir_module_add_value(builder->ctx.module, &const_array_value);
|
||||
Assert(const_array_ref != SCC_IR_REF_NULL);
|
||||
Assert(const_array_ref != SCC_IR_REF_nullptr);
|
||||
|
||||
// 3. 创建全局变量节点,类型为指针,初始值指向常量数组
|
||||
char *name = scc_malloc(32);
|
||||
@@ -124,7 +135,7 @@ scc_ir_builder_const_string(scc_ir_builder_t *builder, const char *str,
|
||||
builder->ctx.module, &(scc_ir_value_t){
|
||||
.name = name,
|
||||
.tag = SCC_IR_VALUE_TAG_GLOBAL_ALLOC,
|
||||
.type = ptr_type_ref,
|
||||
.type = array_type_ref,
|
||||
.data.global_alloc.value = const_array_ref,
|
||||
});
|
||||
scc_snprintf(name, 32, "$G%u", global_value_ref);
|
||||
@@ -135,7 +146,7 @@ scc_ir_builder_const_string(scc_ir_builder_t *builder, const char *str,
|
||||
builder->ctx.module, &(scc_ir_value_t){
|
||||
.tag = SCC_IR_VALUE_TAG_GET_PTR,
|
||||
.data.get_ptr.src_addr = global_value_ref,
|
||||
.data.get_ptr.index = SCC_IR_VALUE_TAG_NULL,
|
||||
.data.get_ptr.index = SCC_IR_VALUE_TAG_NULLPTR,
|
||||
});
|
||||
scc_ir_builder_add_instr(builder, pointer_to_global_value);
|
||||
return pointer_to_global_value;
|
||||
@@ -144,7 +155,7 @@ scc_ir_builder_const_string(scc_ir_builder_t *builder, const char *str,
|
||||
/**
|
||||
* @brief 开始构建函数
|
||||
* @param func_ref 函数引用
|
||||
* @param param_names 参数名列表(可为NULL)
|
||||
* @param param_names 参数名列表(可为nullptr)
|
||||
* @return void
|
||||
*/
|
||||
void scc_ir_builder_begin_func(scc_ir_builder_t *builder,
|
||||
@@ -164,7 +175,7 @@ scc_ir_func_ref_t scc_ir_builder_current_func(scc_ir_builder_t *builder);
|
||||
/**
|
||||
* @brief 创建一个新的基本块,并自动添加到当前函数中,但不改变当前块。
|
||||
* @param builder IR构建器
|
||||
* @param label 基本块标签(可为 NULL,自动生成)
|
||||
* @param label 基本块标签(可为 nullptr,自动生成)
|
||||
* @return 新基本块的引用
|
||||
*/
|
||||
scc_ir_bblock_ref_t scc_ir_builder_bblock(scc_ir_builder_t *builder,
|
||||
@@ -172,7 +183,7 @@ scc_ir_bblock_ref_t scc_ir_builder_bblock(scc_ir_builder_t *builder,
|
||||
|
||||
/**
|
||||
* @brief 开始构建新的基本块
|
||||
* @param label 基本块标签(可为NULL,自动生成)
|
||||
* @param label 基本块标签(可为nullptr,自动生成)
|
||||
* @return 基本块引用
|
||||
*/
|
||||
scc_ir_bblock_ref_t scc_ir_builder_begin_bblock(scc_ir_builder_t *builder,
|
||||
@@ -193,7 +204,7 @@ void scc_ir_builder_set_current_bblock(scc_ir_builder_t *builder,
|
||||
/**
|
||||
* @brief 创建alloca指令(在当前基本块中)
|
||||
* @param type 分配的类型
|
||||
* @param name 变量名(可为NULL)
|
||||
* @param name 变量名(可为nullptr)
|
||||
*/
|
||||
scc_ir_value_ref_t scc_ir_builder_alloca(scc_ir_builder_t *builder,
|
||||
scc_ir_type_ref_t type,
|
||||
|
||||
@@ -3,7 +3,7 @@
|
||||
|
||||
#include <scc_core.h>
|
||||
|
||||
#define SCC_IR_REF_NULL 0
|
||||
#define SCC_IR_REF_nullptr 0
|
||||
|
||||
typedef unsigned int ir_handle_t;
|
||||
typedef const char *scc_ir_label_t;
|
||||
@@ -86,7 +86,8 @@ struct scc_ir_func {
|
||||
};
|
||||
|
||||
typedef enum scc_ir_value_tag {
|
||||
SCC_IR_VALUE_TAG_NULL,
|
||||
SCC_IR_VALUE_TAG_NULLPTR,
|
||||
SCC_IR_VALUE_TAG_BUILTIN,
|
||||
SCC_IR_VALUE_TAG_CONST_INT,
|
||||
SCC_IR_VALUE_TAG_CONST_UINT,
|
||||
SCC_IR_VALUE_TAG_CONST_FLOAT,
|
||||
@@ -175,12 +176,60 @@ typedef union {
|
||||
u8 float_any[16];
|
||||
} scc_ir_const_float_t;
|
||||
|
||||
typedef enum {
|
||||
SCC_IR_BUILTIN_TAG_MEMCPY,
|
||||
SCC_IR_BUILTIN_TAG_MEMSET,
|
||||
SCC_IR_BUILTIN_TAG_VA_START,
|
||||
SCC_IR_BUILTIN_TAG_VA_ARG,
|
||||
SCC_IR_BUILTIN_TAG_VA_END,
|
||||
SCC_IR_BUILTIN_TAG_VA_COPY,
|
||||
} scc_ir_builtin_tag_t;
|
||||
|
||||
typedef struct {
|
||||
scc_ir_builtin_tag_t tag;
|
||||
union {
|
||||
struct {
|
||||
scc_ir_value_ref_t dest;
|
||||
scc_ir_value_ref_t src;
|
||||
scc_ir_value_ref_t size;
|
||||
} memcpy;
|
||||
struct {
|
||||
scc_ir_value_ref_t dest;
|
||||
scc_ir_value_ref_t value;
|
||||
scc_ir_value_ref_t size;
|
||||
} memset;
|
||||
struct {
|
||||
scc_ir_value_ref_t ap; // va_list 的地址(i8* 或 struct*)
|
||||
scc_ir_value_ref_t last; // 最后一个固定参数的引用(用于 va_start)
|
||||
} va_start;
|
||||
struct {
|
||||
scc_ir_value_ref_t ap; // va_list 的地址
|
||||
scc_ir_type_ref_t type; // 要提取的参数的类型
|
||||
} va_arg;
|
||||
struct {
|
||||
scc_ir_value_ref_t ap; // va_list 的地址
|
||||
} va_end;
|
||||
struct {
|
||||
scc_ir_value_ref_t dest; // 目标 va_list 地址
|
||||
scc_ir_value_ref_t src; // 源 va_list 地址
|
||||
} va_copy;
|
||||
} func;
|
||||
} scc_ir_builtin_t;
|
||||
|
||||
typedef enum {
|
||||
SCC_IR_LINKAGE_EXTERNAL,
|
||||
SCC_IR_LINKAGE_INTERNAL,
|
||||
SCC_IR_LINKAGE_PRIVATE,
|
||||
SCC_IR_LINKAGE_WEAK,
|
||||
} scc_ir_linkage_t;
|
||||
|
||||
struct scc_ir_value {
|
||||
scc_ir_type_ref_t type;
|
||||
scc_ir_label_t name;
|
||||
scc_ir_node_ref_vec_t used_by;
|
||||
scc_ir_value_tag_t tag;
|
||||
union {
|
||||
scc_ir_builtin_t builtin;
|
||||
scc_ir_const_int_t const_int;
|
||||
scc_ir_const_uint_t const_uint;
|
||||
scc_ir_const_float_t const_float;
|
||||
|
||||
@@ -42,7 +42,7 @@ scc_ir_func_t *scc_ir_module_get_func(scc_ir_module_t *ctx,
|
||||
static inline scc_ir_type_t *
|
||||
scc_ir_module_get_type_by_value(scc_ir_module_t *ctx, scc_ir_value_ref_t ref) {
|
||||
scc_ir_value_t *value = scc_ir_module_get_value(ctx, ref);
|
||||
Assert(value != null);
|
||||
Assert(value != nullptr);
|
||||
return scc_ir_module_get_type(ctx, value->type);
|
||||
}
|
||||
|
||||
|
||||
@@ -8,8 +8,8 @@ void scc_ir_type_init(scc_ir_type_t *in, scc_ir_type_tag_t tag);
|
||||
void scc_ir_bblock_init(scc_ir_bblock_t *in, const char *label);
|
||||
void scc_ir_func_init(scc_ir_func_t *in, const char *name);
|
||||
|
||||
// node name can be null ptr
|
||||
void scc_ir_node_init(scc_ir_value_t *in, const char *name,
|
||||
scc_ir_value_tag_t tag);
|
||||
// node name can be nullptr ptr
|
||||
void scc_ir_value_init(scc_ir_value_t *in, const char *name,
|
||||
scc_ir_value_tag_t tag);
|
||||
|
||||
#endif /* __SCC_IR_H__ */
|
||||
|
||||
@@ -4,8 +4,8 @@
|
||||
#define GET_MODULE(builder) (&(builder->cprog->module))
|
||||
|
||||
void scc_ir_builder_init(scc_ir_builder_t *builder, scc_ir_cprog_t *cprog) {
|
||||
builder->current_bblock = SCC_IR_REF_NULL;
|
||||
builder->current_func = SCC_IR_REF_NULL;
|
||||
builder->current_bblock = SCC_IR_REF_nullptr;
|
||||
builder->current_func = SCC_IR_REF_nullptr;
|
||||
builder->cprog = cprog;
|
||||
|
||||
scc_ir_ctx_init(&builder->ctx, GET_MODULE(builder));
|
||||
@@ -40,12 +40,12 @@ void scc_ir_builder_begin_func(scc_ir_builder_t *builder,
|
||||
scc_ir_type_t *func_type =
|
||||
scc_ir_module_get_type(GET_MODULE(builder), func_ptr->type);
|
||||
|
||||
if (func_type == null || func_type->tag != SCC_IR_TYPE_FUNC) {
|
||||
if (func_type == nullptr || func_type->tag != SCC_IR_TYPE_FUNC) {
|
||||
LOG_ERROR("Invalid function type");
|
||||
return;
|
||||
}
|
||||
|
||||
if (func_ptr == null) {
|
||||
if (func_ptr == nullptr) {
|
||||
LOG_ERROR("Invalid function reference");
|
||||
return;
|
||||
}
|
||||
@@ -57,7 +57,7 @@ void scc_ir_builder_begin_func(scc_ir_builder_t *builder,
|
||||
}
|
||||
|
||||
scc_ir_type_ref_vec_t params = func_type->data.function.params;
|
||||
func_type = null;
|
||||
func_type = nullptr;
|
||||
scc_vec_foreach(params, i) {
|
||||
scc_ir_type_ref_t param_type = scc_vec_at(params, i);
|
||||
|
||||
@@ -67,7 +67,7 @@ void scc_ir_builder_begin_func(scc_ir_builder_t *builder,
|
||||
GET_MODULE(builder),
|
||||
&(scc_ir_type_t){.tag = SCC_IR_TYPE_PTR,
|
||||
.data.pointer.base = param_type});
|
||||
param_node.name = param_names ? param_names[i] : null;
|
||||
param_node.name = param_names ? param_names[i] : nullptr;
|
||||
param_node.data.arg_ref.idx = i;
|
||||
scc_vec_init(param_node.used_by);
|
||||
|
||||
@@ -81,7 +81,7 @@ void scc_ir_builder_begin_func(scc_ir_builder_t *builder,
|
||||
void scc_ir_builder_end_func(scc_ir_builder_t *builder) {
|
||||
scc_ir_func_t *func_ptr =
|
||||
scc_ir_module_get_func(GET_MODULE(builder), builder->current_func);
|
||||
if (func_ptr == null) {
|
||||
if (func_ptr == nullptr) {
|
||||
LOG_FATAL("Invalid function reference");
|
||||
return;
|
||||
}
|
||||
@@ -157,30 +157,30 @@ scc_ir_value_ref_t scc_ir_builder_alloca(scc_ir_builder_t *builder,
|
||||
&(scc_ir_type_t){.tag = SCC_IR_TYPE_PTR, .data.pointer.base = type});
|
||||
alloc_node.name = name;
|
||||
|
||||
scc_ir_value_ref_t node_ref =
|
||||
scc_ir_value_ref_t value_ref =
|
||||
scc_ir_module_add_value(GET_MODULE(builder), &alloc_node);
|
||||
|
||||
// 添加到当前基本块
|
||||
scc_ir_builder_add_instr(builder, node_ref);
|
||||
scc_ir_builder_add_instr(builder, value_ref);
|
||||
|
||||
return node_ref;
|
||||
return value_ref;
|
||||
}
|
||||
|
||||
scc_ir_value_ref_t scc_ir_builder_func_arg_ref(scc_ir_builder_t *builder,
|
||||
scc_ir_type_ref_t type,
|
||||
const char *name,
|
||||
usize arg_idx) {
|
||||
scc_ir_value_t node = {0};
|
||||
node.tag = SCC_IR_VALUE_TAG_FUNC_ARG_REF;
|
||||
node.type = type;
|
||||
node.name = name;
|
||||
node.data.arg_ref.idx = arg_idx;
|
||||
scc_ir_value_t value = {0};
|
||||
value.tag = SCC_IR_VALUE_TAG_FUNC_ARG_REF;
|
||||
value.type = type;
|
||||
value.name = name;
|
||||
value.data.arg_ref.idx = arg_idx;
|
||||
|
||||
scc_ir_value_ref_t node_ref =
|
||||
scc_ir_module_add_value(GET_MODULE(builder), &node);
|
||||
scc_ir_value_ref_t value_ref =
|
||||
scc_ir_module_add_value(GET_MODULE(builder), &value);
|
||||
// 添加到当前基本块
|
||||
scc_ir_builder_add_instr(builder, node_ref);
|
||||
return node_ref;
|
||||
scc_ir_builder_add_instr(builder, value_ref);
|
||||
return value_ref;
|
||||
}
|
||||
|
||||
scc_ir_value_ref_t scc_ir_builder_load(scc_ir_builder_t *builder,
|
||||
@@ -200,31 +200,31 @@ scc_ir_value_ref_t scc_ir_builder_load(scc_ir_builder_t *builder,
|
||||
}
|
||||
}
|
||||
|
||||
scc_ir_value_ref_t node_ref =
|
||||
scc_ir_value_ref_t value_ref =
|
||||
scc_ir_module_add_value(GET_MODULE(builder), &load_node);
|
||||
|
||||
// 添加到当前基本块
|
||||
scc_ir_builder_add_instr(builder, node_ref);
|
||||
scc_ir_builder_add_instr(builder, value_ref);
|
||||
|
||||
return node_ref;
|
||||
return value_ref;
|
||||
}
|
||||
|
||||
scc_ir_value_ref_t scc_ir_builder_store(scc_ir_builder_t *builder,
|
||||
scc_ir_value_ref_t target,
|
||||
scc_ir_value_ref_t value) {
|
||||
Assert(target != SCC_IR_REF_NULL && value != SCC_IR_REF_NULL);
|
||||
Assert(target != SCC_IR_REF_nullptr && value != SCC_IR_REF_nullptr);
|
||||
scc_ir_value_t store_node = {0};
|
||||
store_node.tag = SCC_IR_VALUE_TAG_STORE;
|
||||
store_node.data.store.target = target;
|
||||
store_node.data.store.value = value;
|
||||
|
||||
scc_ir_value_ref_t node_ref =
|
||||
scc_ir_value_ref_t value_ref =
|
||||
scc_ir_module_add_value(GET_MODULE(builder), &store_node);
|
||||
|
||||
// 添加到当前基本块
|
||||
scc_ir_builder_add_instr(builder, node_ref);
|
||||
scc_ir_builder_add_instr(builder, value_ref);
|
||||
|
||||
return node_ref;
|
||||
return value_ref;
|
||||
}
|
||||
|
||||
scc_ir_value_ref_t scc_ir_builder_get_ptr(scc_ir_builder_t *builder,
|
||||
@@ -242,13 +242,13 @@ scc_ir_value_ref_t scc_ir_builder_get_ptr(scc_ir_builder_t *builder,
|
||||
get_ptr_node.type = src_node->type;
|
||||
}
|
||||
|
||||
scc_ir_value_ref_t node_ref =
|
||||
scc_ir_value_ref_t value_ref =
|
||||
scc_ir_module_add_value(GET_MODULE(builder), &get_ptr_node);
|
||||
|
||||
// 添加到当前基本块
|
||||
scc_ir_builder_add_instr(builder, node_ref);
|
||||
scc_ir_builder_add_instr(builder, value_ref);
|
||||
|
||||
return node_ref;
|
||||
return value_ref;
|
||||
}
|
||||
|
||||
scc_ir_value_ref_t scc_ir_builder_binop(scc_ir_builder_t *builder,
|
||||
@@ -268,13 +268,13 @@ scc_ir_value_ref_t scc_ir_builder_binop(scc_ir_builder_t *builder,
|
||||
binop_node.type = lhs_node->type;
|
||||
}
|
||||
|
||||
scc_ir_value_ref_t node_ref =
|
||||
scc_ir_value_ref_t value_ref =
|
||||
scc_ir_module_add_value(GET_MODULE(builder), &binop_node);
|
||||
|
||||
// 添加到当前基本块
|
||||
scc_ir_builder_add_instr(builder, node_ref);
|
||||
scc_ir_builder_add_instr(builder, value_ref);
|
||||
|
||||
return node_ref;
|
||||
return value_ref;
|
||||
}
|
||||
|
||||
scc_ir_value_ref_t scc_ir_builder_cmp(scc_ir_builder_t *builder,
|
||||
@@ -291,13 +291,13 @@ scc_ir_value_ref_t scc_ir_builder_cmp(scc_ir_builder_t *builder,
|
||||
cmp_node.type =
|
||||
0; // FIXME scc_ir_module_get_builtin_i32(GET_MODULE(builder));
|
||||
|
||||
scc_ir_value_ref_t node_ref =
|
||||
scc_ir_value_ref_t value_ref =
|
||||
scc_ir_module_add_value(GET_MODULE(builder), &cmp_node);
|
||||
|
||||
// 添加到当前基本块
|
||||
scc_ir_builder_add_instr(builder, node_ref);
|
||||
scc_ir_builder_add_instr(builder, value_ref);
|
||||
|
||||
return node_ref;
|
||||
return value_ref;
|
||||
}
|
||||
|
||||
scc_ir_value_ref_t scc_ir_builder_jump(scc_ir_builder_t *builder,
|
||||
@@ -306,13 +306,13 @@ scc_ir_value_ref_t scc_ir_builder_jump(scc_ir_builder_t *builder,
|
||||
jump_node.tag = SCC_IR_VALUE_TAG_JUMP;
|
||||
jump_node.data.jump.target_bblock = target;
|
||||
|
||||
scc_ir_value_ref_t node_ref =
|
||||
scc_ir_value_ref_t value_ref =
|
||||
scc_ir_module_add_value(GET_MODULE(builder), &jump_node);
|
||||
|
||||
// 添加到当前基本块
|
||||
scc_ir_builder_add_instr(builder, node_ref);
|
||||
scc_ir_builder_add_instr(builder, value_ref);
|
||||
|
||||
return node_ref;
|
||||
return value_ref;
|
||||
}
|
||||
|
||||
scc_ir_value_ref_t scc_ir_builder_branch(scc_ir_builder_t *builder,
|
||||
@@ -325,13 +325,13 @@ scc_ir_value_ref_t scc_ir_builder_branch(scc_ir_builder_t *builder,
|
||||
branch_node.data.branch.true_bblock = true_target;
|
||||
branch_node.data.branch.false_bblock = false_target;
|
||||
|
||||
scc_ir_value_ref_t node_ref =
|
||||
scc_ir_value_ref_t value_ref =
|
||||
scc_ir_module_add_value(GET_MODULE(builder), &branch_node);
|
||||
|
||||
// 添加到当前基本块
|
||||
scc_ir_builder_add_instr(builder, node_ref);
|
||||
scc_ir_builder_add_instr(builder, value_ref);
|
||||
|
||||
return node_ref;
|
||||
return value_ref;
|
||||
}
|
||||
|
||||
scc_ir_value_ref_t scc_ir_builder_call(scc_ir_builder_t *builder,
|
||||
@@ -358,13 +358,13 @@ scc_ir_value_ref_t scc_ir_builder_call(scc_ir_builder_t *builder,
|
||||
}
|
||||
}
|
||||
|
||||
scc_ir_value_ref_t node_ref =
|
||||
scc_ir_value_ref_t value_ref =
|
||||
scc_ir_module_add_value(GET_MODULE(builder), &call_node);
|
||||
|
||||
// 添加到当前基本块
|
||||
scc_ir_builder_add_instr(builder, node_ref);
|
||||
scc_ir_builder_add_instr(builder, value_ref);
|
||||
|
||||
return node_ref;
|
||||
return value_ref;
|
||||
}
|
||||
|
||||
scc_ir_value_ref_t scc_ir_builder_ret(scc_ir_builder_t *builder,
|
||||
@@ -373,13 +373,13 @@ scc_ir_value_ref_t scc_ir_builder_ret(scc_ir_builder_t *builder,
|
||||
ret_node.tag = SCC_IR_VALUE_TAG_RET;
|
||||
ret_node.data.ret.ret_val = value;
|
||||
|
||||
scc_ir_value_ref_t node_ref =
|
||||
scc_ir_value_ref_t value_ref =
|
||||
scc_ir_module_add_value(GET_MODULE(builder), &ret_node);
|
||||
|
||||
// 添加到当前基本块
|
||||
scc_ir_builder_add_instr(builder, node_ref);
|
||||
scc_ir_builder_add_instr(builder, value_ref);
|
||||
|
||||
return node_ref;
|
||||
return value_ref;
|
||||
}
|
||||
|
||||
scc_ir_value_ref_t scc_ir_builder_ret_void(scc_ir_builder_t *builder) {
|
||||
@@ -387,10 +387,10 @@ scc_ir_value_ref_t scc_ir_builder_ret_void(scc_ir_builder_t *builder) {
|
||||
ret_node.tag = SCC_IR_VALUE_TAG_RET;
|
||||
ret_node.data.ret.ret_val = 0; // 无返回值
|
||||
|
||||
scc_ir_value_ref_t node_ref =
|
||||
scc_ir_value_ref_t value_ref =
|
||||
scc_ir_module_add_value(GET_MODULE(builder), &ret_node);
|
||||
|
||||
// 添加到当前基本块
|
||||
scc_ir_builder_add_instr(builder, node_ref);
|
||||
return node_ref;
|
||||
scc_ir_builder_add_instr(builder, value_ref);
|
||||
return value_ref;
|
||||
}
|
||||
|
||||
@@ -88,21 +88,17 @@ static int cmp_type(const void *_key1, const void *_key2) {
|
||||
return 0; // 基本类型,tag相同即可
|
||||
case SCC_IR_TYPE_PTR:
|
||||
return key1->data.pointer.base != key2->data.pointer.base;
|
||||
|
||||
case SCC_IR_TYPE_ARRAY:
|
||||
return (key1->data.array.base != key2->data.array.base) ||
|
||||
(key1->data.array.len != key2->data.array.len);
|
||||
|
||||
case SCC_IR_TYPE_FUNC: {
|
||||
if (key1->data.function.ret_type != key2->data.function.ret_type) {
|
||||
return 1;
|
||||
}
|
||||
|
||||
if (key1->data.function.params.size !=
|
||||
key2->data.function.params.size) {
|
||||
return 1;
|
||||
}
|
||||
|
||||
for (usize i = 0; i < key1->data.function.params.size; i++) {
|
||||
if (key1->data.function.params.data[i] !=
|
||||
key2->data.function.params.data[i]) {
|
||||
@@ -136,6 +132,7 @@ void scc_ir_ctx_drop(scc_ir_ctx_t *ctx) {
|
||||
|
||||
scc_ir_type_ref_t scc_ir_ctx_get_type(scc_ir_ctx_t *ctx,
|
||||
const scc_ir_type_t *type_desc) {
|
||||
Assert(type_desc->tag != SCC_IR_TYPE_unknown);
|
||||
// 先查哈希表
|
||||
void *found = scc_hashtable_get(&ctx->type_uniquing, (void *)type_desc);
|
||||
if (found) {
|
||||
|
||||
@@ -6,7 +6,8 @@
|
||||
|
||||
static const char *get_node_type_str(scc_ir_value_tag_t tag) {
|
||||
static const char *node_types[] = {
|
||||
[SCC_IR_VALUE_TAG_NULL] = "Null",
|
||||
[SCC_IR_VALUE_TAG_NULLPTR] = "NullPtr",
|
||||
[SCC_IR_VALUE_TAG_BUILTIN] = "Builtin",
|
||||
[SCC_IR_VALUE_TAG_CONST_INT] = "ConstInt",
|
||||
[SCC_IR_VALUE_TAG_CONST_UINT] = "ConstUint",
|
||||
[SCC_IR_VALUE_TAG_CONST_FLOAT] = "ConstFloat",
|
||||
@@ -81,56 +82,57 @@ static inline void dump_child_node_ref(scc_ir_dump_ctx_t *ctx,
|
||||
}
|
||||
|
||||
static void dump_const_int_node(scc_ir_dump_ctx_t *ctx,
|
||||
const scc_ir_value_t *node) {
|
||||
const scc_ir_value_t *value) {
|
||||
scc_tree_dump_push(ctx->dump_ctx, true);
|
||||
scc_tree_dump_begin_line(ctx->dump_ctx);
|
||||
scc_tree_dump_value(ctx->dump_ctx, "%d", node->data.const_int.int32);
|
||||
scc_tree_dump_value(ctx->dump_ctx, "%d", value->data.const_int.int32);
|
||||
scc_tree_dump_pop(ctx->dump_ctx);
|
||||
}
|
||||
|
||||
static void dump_op_node(scc_ir_dump_ctx_t *ctx, const scc_ir_value_t *node) {
|
||||
static void dump_op_node(scc_ir_dump_ctx_t *ctx, const scc_ir_value_t *value) {
|
||||
scc_tree_dump_push(ctx->dump_ctx, false);
|
||||
scc_tree_dump_begin_line(ctx->dump_ctx);
|
||||
scc_tree_dump_node(ctx->dump_ctx, "op: ");
|
||||
scc_tree_dump_value(ctx->dump_ctx, "%s", get_op_str(node->data.op.op));
|
||||
scc_tree_dump_value(ctx->dump_ctx, "%s", get_op_str(value->data.op.op));
|
||||
scc_tree_dump_pop(ctx->dump_ctx);
|
||||
|
||||
if (node->data.op.lhs)
|
||||
dump_child_node_ref(ctx, node->data.op.lhs,
|
||||
node->data.op.rhs ? false : true);
|
||||
if (node->data.op.rhs)
|
||||
dump_child_node_ref(ctx, node->data.op.rhs, true);
|
||||
if (value->data.op.lhs)
|
||||
dump_child_node_ref(ctx, value->data.op.lhs,
|
||||
value->data.op.rhs ? false : true);
|
||||
if (value->data.op.rhs)
|
||||
dump_child_node_ref(ctx, value->data.op.rhs, true);
|
||||
}
|
||||
|
||||
static void dump_load_node(scc_ir_dump_ctx_t *ctx, const scc_ir_value_t *node) {
|
||||
if (node->data.load.target)
|
||||
dump_child_node_ref(ctx, node->data.load.target, true);
|
||||
static void dump_load_node(scc_ir_dump_ctx_t *ctx,
|
||||
const scc_ir_value_t *value) {
|
||||
if (value->data.load.target)
|
||||
dump_child_node_ref(ctx, value->data.load.target, true);
|
||||
}
|
||||
|
||||
static void dump_store_node(scc_ir_dump_ctx_t *ctx,
|
||||
const scc_ir_value_t *node) {
|
||||
if (node->data.store.target)
|
||||
dump_child_node_ref(ctx, node->data.store.target, false);
|
||||
if (node->data.store.value)
|
||||
dump_child_node_ref(ctx, node->data.store.value, true);
|
||||
const scc_ir_value_t *value) {
|
||||
if (value->data.store.target)
|
||||
dump_child_node_ref(ctx, value->data.store.target, false);
|
||||
if (value->data.store.value)
|
||||
dump_child_node_ref(ctx, value->data.store.value, true);
|
||||
}
|
||||
|
||||
static void dump_get_ptr_node(scc_ir_dump_ctx_t *ctx,
|
||||
const scc_ir_value_t *node) {
|
||||
if (node->data.get_ptr.src_addr)
|
||||
dump_child_node_ref(ctx, node->data.get_ptr.src_addr, false);
|
||||
if (node->data.get_ptr.index)
|
||||
dump_child_node_ref(ctx, node->data.get_ptr.index, true);
|
||||
const scc_ir_value_t *value) {
|
||||
if (value->data.get_ptr.src_addr)
|
||||
dump_child_node_ref(ctx, value->data.get_ptr.src_addr, false);
|
||||
if (value->data.get_ptr.index)
|
||||
dump_child_node_ref(ctx, value->data.get_ptr.index, true);
|
||||
}
|
||||
|
||||
static void dump_branch_node(scc_ir_dump_ctx_t *ctx,
|
||||
const scc_ir_value_t *node) {
|
||||
if (node->data.branch.cond)
|
||||
dump_child_node_ref(ctx, node->data.branch.cond, false);
|
||||
const scc_ir_value_t *value) {
|
||||
if (value->data.branch.cond)
|
||||
dump_child_node_ref(ctx, value->data.branch.cond, false);
|
||||
|
||||
if (node->data.branch.true_bblock) {
|
||||
if (value->data.branch.true_bblock) {
|
||||
scc_ir_bblock_t *true_bblock = scc_ir_module_get_bblock(
|
||||
GET_MODULE(ctx), node->data.branch.true_bblock);
|
||||
GET_MODULE(ctx), value->data.branch.true_bblock);
|
||||
if (true_bblock) {
|
||||
scc_tree_dump_begin_line(ctx->dump_ctx);
|
||||
scc_tree_dump_node(ctx->dump_ctx, "TrueBlock: ");
|
||||
@@ -139,9 +141,9 @@ static void dump_branch_node(scc_ir_dump_ctx_t *ctx,
|
||||
: "<unnamed>");
|
||||
}
|
||||
}
|
||||
if (node->data.branch.false_bblock) {
|
||||
if (value->data.branch.false_bblock) {
|
||||
scc_ir_bblock_t *false_bblock = scc_ir_module_get_bblock(
|
||||
GET_MODULE(ctx), node->data.branch.false_bblock);
|
||||
GET_MODULE(ctx), value->data.branch.false_bblock);
|
||||
if (false_bblock) {
|
||||
scc_tree_dump_begin_line(ctx->dump_ctx);
|
||||
scc_tree_dump_node(ctx->dump_ctx, "FalseBlock: ");
|
||||
@@ -152,45 +154,47 @@ static void dump_branch_node(scc_ir_dump_ctx_t *ctx,
|
||||
}
|
||||
}
|
||||
|
||||
static void dump_jump_node(scc_ir_dump_ctx_t *ctx, const scc_ir_value_t *node) {
|
||||
static void dump_jump_node(scc_ir_dump_ctx_t *ctx,
|
||||
const scc_ir_value_t *value) {
|
||||
scc_tree_dump_begin_line(ctx->dump_ctx);
|
||||
if (node->data.jump.target_bblock) {
|
||||
if (value->data.jump.target_bblock) {
|
||||
scc_ir_bblock_t *target = scc_ir_module_get_bblock(
|
||||
GET_MODULE(ctx), node->data.jump.target_bblock);
|
||||
GET_MODULE(ctx), value->data.jump.target_bblock);
|
||||
if (target)
|
||||
scc_tree_dump_value(ctx->dump_ctx, "to '%s'",
|
||||
target->label ? target->label : "<unnamed>");
|
||||
else
|
||||
scc_tree_dump_value(ctx->dump_ctx, "to invalid block");
|
||||
} else {
|
||||
scc_tree_dump_value(ctx->dump_ctx, "to NULL");
|
||||
scc_tree_dump_value(ctx->dump_ctx, "to nullptr");
|
||||
}
|
||||
}
|
||||
|
||||
static void dump_call_node(scc_ir_dump_ctx_t *ctx, const scc_ir_value_t *node) {
|
||||
static void dump_call_node(scc_ir_dump_ctx_t *ctx,
|
||||
const scc_ir_value_t *value) {
|
||||
scc_tree_dump_begin_line(ctx->dump_ctx);
|
||||
if (node->data.call.callee) {
|
||||
if (value->data.call.callee) {
|
||||
scc_ir_func_t *callee =
|
||||
scc_ir_module_get_func(GET_MODULE(ctx), node->data.call.callee);
|
||||
scc_ir_module_get_func(GET_MODULE(ctx), value->data.call.callee);
|
||||
scc_tree_dump_value(ctx->dump_ctx, "func='%s'",
|
||||
callee ? (callee->name ? callee->name : "<unnamed>")
|
||||
: "<invalid>");
|
||||
} else {
|
||||
scc_tree_dump_value(ctx->dump_ctx, "func=NULL");
|
||||
scc_tree_dump_value(ctx->dump_ctx, "func=nullptr");
|
||||
}
|
||||
|
||||
for (usize i = 0; i < scc_vec_size(node->data.call.args); i++) {
|
||||
cbool is_last = (i + 1 == scc_vec_size(node->data.call.args));
|
||||
for (usize i = 0; i < scc_vec_size(value->data.call.args); i++) {
|
||||
cbool is_last = (i + 1 == scc_vec_size(value->data.call.args));
|
||||
scc_tree_dump_push(ctx->dump_ctx, is_last);
|
||||
scc_ir_value_ref_t arg = scc_vec_at(node->data.call.args, i);
|
||||
scc_ir_value_ref_t arg = scc_vec_at(value->data.call.args, i);
|
||||
dump_child_node_ref(ctx, arg, is_last);
|
||||
scc_tree_dump_pop(ctx->dump_ctx);
|
||||
}
|
||||
}
|
||||
|
||||
static void dump_ret_node(scc_ir_dump_ctx_t *ctx, const scc_ir_value_t *node) {
|
||||
if (node->data.ret.ret_val)
|
||||
dump_child_node_ref(ctx, node->data.ret.ret_val, true);
|
||||
static void dump_ret_node(scc_ir_dump_ctx_t *ctx, const scc_ir_value_t *value) {
|
||||
if (value->data.ret.ret_val)
|
||||
dump_child_node_ref(ctx, value->data.ret.ret_val, true);
|
||||
}
|
||||
|
||||
void scc_ir_dump_ctx_init(scc_ir_dump_ctx_t *ctx, scc_tree_dump_t *td,
|
||||
@@ -199,20 +203,20 @@ void scc_ir_dump_ctx_init(scc_ir_dump_ctx_t *ctx, scc_tree_dump_t *td,
|
||||
ctx->dump_ctx = td;
|
||||
}
|
||||
|
||||
void scc_ir_dump_value(scc_ir_dump_ctx_t *ctx, scc_ir_value_ref_t node_ref) {
|
||||
scc_ir_value_t *node = scc_ir_module_get_value(GET_MODULE(ctx), node_ref);
|
||||
if (!node) {
|
||||
LOG_ERROR("Invalid node ref");
|
||||
void scc_ir_dump_value(scc_ir_dump_ctx_t *ctx, scc_ir_value_ref_t value_ref) {
|
||||
scc_ir_value_t *value = scc_ir_module_get_value(GET_MODULE(ctx), value_ref);
|
||||
if (!value) {
|
||||
LOG_ERROR("Invalid value ref");
|
||||
return;
|
||||
}
|
||||
|
||||
scc_tree_dump_begin_line(ctx->dump_ctx);
|
||||
scc_tree_dump_node(ctx->dump_ctx, "%s", get_node_type_str(node->tag));
|
||||
if (node->name && node->name[0])
|
||||
scc_tree_dump_value(ctx->dump_ctx, " [%s]", node->name);
|
||||
if (node->type) {
|
||||
scc_tree_dump_node(ctx->dump_ctx, "%s", get_node_type_str(value->tag));
|
||||
if (value->name && value->name[0])
|
||||
scc_tree_dump_value(ctx->dump_ctx, " [%s]", value->name);
|
||||
if (value->type) {
|
||||
scc_ir_type_t *type =
|
||||
scc_ir_module_get_type(GET_MODULE(ctx), node->type);
|
||||
scc_ir_module_get_type(GET_MODULE(ctx), value->type);
|
||||
if (type) {
|
||||
scc_tree_dump_append(ctx->dump_ctx, " : ");
|
||||
scc_tree_dump_value(ctx->dump_ctx, "%s",
|
||||
@@ -220,39 +224,39 @@ void scc_ir_dump_value(scc_ir_dump_ctx_t *ctx, scc_ir_value_ref_t node_ref) {
|
||||
}
|
||||
}
|
||||
|
||||
switch (node->tag) {
|
||||
switch (value->tag) {
|
||||
case SCC_IR_VALUE_TAG_CONST_INT:
|
||||
dump_const_int_node(ctx, node);
|
||||
dump_const_int_node(ctx, value);
|
||||
break;
|
||||
case SCC_IR_VALUE_TAG_ALLOC:
|
||||
break;
|
||||
case SCC_IR_VALUE_TAG_LOAD:
|
||||
dump_load_node(ctx, node);
|
||||
dump_load_node(ctx, value);
|
||||
break;
|
||||
case SCC_IR_VALUE_TAG_STORE:
|
||||
dump_store_node(ctx, node);
|
||||
dump_store_node(ctx, value);
|
||||
break;
|
||||
case SCC_IR_VALUE_TAG_GET_PTR:
|
||||
dump_get_ptr_node(ctx, node);
|
||||
dump_get_ptr_node(ctx, value);
|
||||
break;
|
||||
case SCC_IR_VALUE_TAG_OP:
|
||||
dump_op_node(ctx, node);
|
||||
dump_op_node(ctx, value);
|
||||
break;
|
||||
case SCC_IR_VALUE_TAG_BRANCH:
|
||||
dump_branch_node(ctx, node);
|
||||
dump_branch_node(ctx, value);
|
||||
break;
|
||||
case SCC_IR_VALUE_TAG_JUMP:
|
||||
dump_jump_node(ctx, node);
|
||||
dump_jump_node(ctx, value);
|
||||
break;
|
||||
case SCC_IR_VALUE_TAG_CALL:
|
||||
dump_call_node(ctx, node);
|
||||
dump_call_node(ctx, value);
|
||||
break;
|
||||
case SCC_IR_VALUE_TAG_RET:
|
||||
dump_ret_node(ctx, node);
|
||||
dump_ret_node(ctx, value);
|
||||
break;
|
||||
default:
|
||||
scc_tree_dump_value(ctx->dump_ctx, "unknown");
|
||||
scc_tree_dump_append_fmt(ctx->dump_ctx, " tag(%d)", node->tag);
|
||||
scc_tree_dump_append_fmt(ctx->dump_ctx, " tag(%d)", value->tag);
|
||||
break;
|
||||
}
|
||||
}
|
||||
@@ -434,73 +438,99 @@ void scc_ir_dump_type_linear(scc_ir_dump_ctx_t *ctx,
|
||||
}
|
||||
}
|
||||
|
||||
static void format_node_ref_or_value(scc_ir_dump_ctx_t *ctx,
|
||||
scc_ir_value_ref_t node_ref) {
|
||||
scc_ir_value_t *node = scc_ir_module_get_value(GET_MODULE(ctx), node_ref);
|
||||
if (!node) {
|
||||
scc_tree_dump_append_fmt(ctx->dump_ctx, "%%%u", node_ref);
|
||||
static void format_ref_or_value(scc_ir_dump_ctx_t *ctx,
|
||||
scc_ir_value_ref_t value_ref) {
|
||||
scc_ir_value_t *value = scc_ir_module_get_value(GET_MODULE(ctx), value_ref);
|
||||
if (!value) {
|
||||
scc_tree_dump_append_fmt(ctx->dump_ctx, "%%%u", value_ref);
|
||||
return;
|
||||
}
|
||||
if (node->tag == SCC_IR_VALUE_TAG_CONST_INT) {
|
||||
if (value->tag == SCC_IR_VALUE_TAG_CONST_INT) {
|
||||
scc_tree_dump_append_fmt(ctx->dump_ctx, "%d",
|
||||
node->data.const_int.int32);
|
||||
value->data.const_int.int32);
|
||||
return;
|
||||
}
|
||||
if (node->name && node->name[0] != '\0') {
|
||||
scc_tree_dump_node(ctx->dump_ctx, "%%%u[%s]", node_ref, node->name);
|
||||
if (value->name && value->name[0] != '\0') {
|
||||
scc_tree_dump_node(ctx->dump_ctx, "%%%u[%s]", value_ref, value->name);
|
||||
} else {
|
||||
scc_tree_dump_node(ctx->dump_ctx, "%%%u", node_ref);
|
||||
scc_tree_dump_node(ctx->dump_ctx, "%%%u", value_ref);
|
||||
}
|
||||
if (node->type != SCC_IR_REF_NULL) {
|
||||
if (value->type != SCC_IR_REF_nullptr) {
|
||||
scc_tree_dump_append(ctx->dump_ctx, ":");
|
||||
scc_ir_dump_type_linear(ctx, node->type);
|
||||
scc_ir_dump_type_linear(ctx, value->type);
|
||||
}
|
||||
}
|
||||
|
||||
void scc_ir_dump_node_linear(scc_ir_dump_ctx_t *ctx,
|
||||
scc_ir_value_ref_t node_ref) {
|
||||
scc_ir_value_t *node = scc_ir_module_get_value(GET_MODULE(ctx), node_ref);
|
||||
if (!node) {
|
||||
scc_tree_dump_append(ctx->dump_ctx, "<invalid node>\n");
|
||||
void scc_ir_dump_value_linear(scc_ir_dump_ctx_t *ctx,
|
||||
scc_ir_value_ref_t value_ref) {
|
||||
scc_ir_value_t *value = scc_ir_module_get_value(GET_MODULE(ctx), value_ref);
|
||||
if (!value) {
|
||||
scc_tree_dump_append(ctx->dump_ctx, "<invalid value>\n");
|
||||
return;
|
||||
}
|
||||
|
||||
cbool needs_equals = (node->tag != SCC_IR_VALUE_TAG_BRANCH &&
|
||||
node->tag != SCC_IR_VALUE_TAG_JUMP &&
|
||||
node->tag != SCC_IR_VALUE_TAG_RET &&
|
||||
node->tag != SCC_IR_VALUE_TAG_STORE);
|
||||
cbool needs_equals = (value->tag != SCC_IR_VALUE_TAG_BRANCH &&
|
||||
value->tag != SCC_IR_VALUE_TAG_JUMP &&
|
||||
value->tag != SCC_IR_VALUE_TAG_RET &&
|
||||
value->tag != SCC_IR_VALUE_TAG_STORE);
|
||||
|
||||
if (needs_equals) {
|
||||
format_node_ref_or_value(ctx, node_ref);
|
||||
format_ref_or_value(ctx, value_ref);
|
||||
scc_tree_dump_append(ctx->dump_ctx, " = ");
|
||||
}
|
||||
|
||||
switch (node->tag) {
|
||||
switch (value->tag) {
|
||||
case SCC_IR_VALUE_TAG_BUILTIN: {
|
||||
switch (value->data.builtin.tag) {
|
||||
case SCC_IR_BUILTIN_TAG_MEMCPY:
|
||||
scc_tree_dump_append(ctx->dump_ctx, "memcpy");
|
||||
break;
|
||||
case SCC_IR_BUILTIN_TAG_MEMSET:
|
||||
scc_tree_dump_append(ctx->dump_ctx, "memset");
|
||||
break;
|
||||
case SCC_IR_BUILTIN_TAG_VA_ARG:
|
||||
scc_tree_dump_append(ctx->dump_ctx, "va_arg");
|
||||
break;
|
||||
case SCC_IR_BUILTIN_TAG_VA_END:
|
||||
scc_tree_dump_append(ctx->dump_ctx, "va_end");
|
||||
break;
|
||||
case SCC_IR_BUILTIN_TAG_VA_COPY:
|
||||
scc_tree_dump_append(ctx->dump_ctx, "va_copy");
|
||||
break;
|
||||
case SCC_IR_BUILTIN_TAG_VA_START:
|
||||
scc_tree_dump_append(ctx->dump_ctx, "va_start");
|
||||
break;
|
||||
default:
|
||||
Panic("Unknown builtin tag");
|
||||
break;
|
||||
}
|
||||
break;
|
||||
}
|
||||
case SCC_IR_VALUE_TAG_CONST_INT:
|
||||
// 值已经在 format 中输出,这里不需要再做
|
||||
break;
|
||||
case SCC_IR_VALUE_TAG_CONST_UINT: {
|
||||
scc_ir_type_t *type =
|
||||
scc_ir_module_get_type(GET_MODULE(ctx), node->type);
|
||||
Assert(type != null);
|
||||
scc_ir_module_get_type(GET_MODULE(ctx), value->type);
|
||||
Assert(type != nullptr);
|
||||
if (type->tag == SCC_IR_TYPE_u8) {
|
||||
scc_tree_dump_append_fmt(ctx->dump_ctx, "%c",
|
||||
node->data.const_uint.uint8);
|
||||
value->data.const_uint.uint8);
|
||||
} else {
|
||||
scc_tree_dump_append_fmt(ctx->dump_ctx, "%u",
|
||||
node->data.const_uint.uint32);
|
||||
value->data.const_uint.uint32);
|
||||
}
|
||||
break;
|
||||
}
|
||||
case SCC_IR_VALUE_TAG_CONST_FLOAT:
|
||||
scc_tree_dump_append_fmt(ctx->dump_ctx, "%f",
|
||||
node->data.const_float.float32);
|
||||
value->data.const_float.float32);
|
||||
break;
|
||||
case SCC_IR_VALUE_TAG_AGGREGATE:
|
||||
// 聚合类型:递归输出每个元素(每个占一行)
|
||||
scc_vec_foreach(node->data.aggregate.elements, i) {
|
||||
scc_ir_dump_node_linear(
|
||||
ctx, scc_vec_at(node->data.aggregate.elements, i));
|
||||
scc_vec_foreach(value->data.aggregate.elements, i) {
|
||||
scc_ir_dump_value_linear(
|
||||
ctx, scc_vec_at(value->data.aggregate.elements, i));
|
||||
scc_tree_dump_append(ctx->dump_ctx, "\n");
|
||||
}
|
||||
return;
|
||||
@@ -509,88 +539,89 @@ void scc_ir_dump_node_linear(scc_ir_dump_ctx_t *ctx,
|
||||
break;
|
||||
case SCC_IR_VALUE_TAG_LOAD:
|
||||
scc_tree_dump_append(ctx->dump_ctx, "load ");
|
||||
format_node_ref_or_value(ctx, node->data.load.target);
|
||||
format_ref_or_value(ctx, value->data.load.target);
|
||||
break;
|
||||
case SCC_IR_VALUE_TAG_STORE:
|
||||
scc_tree_dump_append(ctx->dump_ctx, "store ");
|
||||
format_node_ref_or_value(ctx, node->data.store.value);
|
||||
format_ref_or_value(ctx, value->data.store.value);
|
||||
scc_tree_dump_append(ctx->dump_ctx, " -> ");
|
||||
format_node_ref_or_value(ctx, node->data.store.target);
|
||||
format_ref_or_value(ctx, value->data.store.target);
|
||||
break;
|
||||
case SCC_IR_VALUE_TAG_GET_ELEM_PTR:
|
||||
case SCC_IR_VALUE_TAG_GET_PTR:
|
||||
scc_tree_dump_append(
|
||||
ctx->dump_ctx,
|
||||
node->tag == SCC_IR_VALUE_TAG_GET_PTR ? "getptr " : "getelemptr ");
|
||||
format_node_ref_or_value(ctx, node->data.get_ptr.src_addr);
|
||||
value->tag == SCC_IR_VALUE_TAG_GET_PTR ? "getptr " : "getelemptr ");
|
||||
format_ref_or_value(ctx, value->data.get_ptr.src_addr);
|
||||
scc_tree_dump_append(ctx->dump_ctx, ", ");
|
||||
format_node_ref_or_value(ctx, node->data.get_ptr.index);
|
||||
format_ref_or_value(ctx, value->data.get_ptr.index);
|
||||
break;
|
||||
case SCC_IR_VALUE_TAG_OP:
|
||||
format_node_ref_or_value(ctx, node->data.op.lhs);
|
||||
format_ref_or_value(ctx, value->data.op.lhs);
|
||||
scc_tree_dump_append_fmt(ctx->dump_ctx, " %s ",
|
||||
get_op_str(node->data.op.op));
|
||||
format_node_ref_or_value(ctx, node->data.op.rhs);
|
||||
get_op_str(value->data.op.op));
|
||||
format_ref_or_value(ctx, value->data.op.rhs);
|
||||
break;
|
||||
case SCC_IR_VALUE_TAG_BRANCH:
|
||||
if (node->data.branch.cond) {
|
||||
if (value->data.branch.cond) {
|
||||
scc_tree_dump_append(ctx->dump_ctx, "br ");
|
||||
format_node_ref_or_value(ctx, node->data.branch.cond);
|
||||
scc_tree_dump_append_fmt(
|
||||
ctx->dump_ctx, ", label %%L%u, label %%L%u",
|
||||
node->data.branch.true_bblock, node->data.branch.false_bblock);
|
||||
format_ref_or_value(ctx, value->data.branch.cond);
|
||||
scc_tree_dump_append_fmt(ctx->dump_ctx,
|
||||
", label %%L%u, label %%L%u",
|
||||
value->data.branch.true_bblock,
|
||||
value->data.branch.false_bblock);
|
||||
} else {
|
||||
scc_tree_dump_append_fmt(ctx->dump_ctx, "br label %%L%u",
|
||||
node->data.branch.true_bblock);
|
||||
value->data.branch.true_bblock);
|
||||
}
|
||||
break;
|
||||
case SCC_IR_VALUE_TAG_JUMP:
|
||||
scc_tree_dump_append_fmt(ctx->dump_ctx, "jmp label %%%u",
|
||||
node->data.jump.target_bblock);
|
||||
scc_tree_dump_append_fmt(ctx->dump_ctx, "jmp label %%L%u",
|
||||
value->data.jump.target_bblock);
|
||||
break;
|
||||
case SCC_IR_VALUE_TAG_CALL: {
|
||||
scc_ir_func_t *func =
|
||||
scc_ir_module_get_func(GET_MODULE(ctx), node->data.call.callee);
|
||||
scc_ir_module_get_func(GET_MODULE(ctx), value->data.call.callee);
|
||||
scc_tree_dump_append_fmt(ctx->dump_ctx, "call @%s(",
|
||||
func ? (func->name ? func->name : "<unnamed>")
|
||||
: "<invalid>");
|
||||
for (usize i = 0; i < scc_vec_size(node->data.call.args); i++) {
|
||||
for (usize i = 0; i < scc_vec_size(value->data.call.args); i++) {
|
||||
if (i > 0)
|
||||
scc_tree_dump_append(ctx->dump_ctx, ", ");
|
||||
format_node_ref_or_value(ctx, scc_vec_at(node->data.call.args, i));
|
||||
format_ref_or_value(ctx, scc_vec_at(value->data.call.args, i));
|
||||
}
|
||||
scc_tree_dump_append(ctx->dump_ctx, ")");
|
||||
break;
|
||||
}
|
||||
case SCC_IR_VALUE_TAG_RET:
|
||||
if (node->data.ret.ret_val != 0) {
|
||||
if (value->data.ret.ret_val != 0) {
|
||||
scc_tree_dump_append(ctx->dump_ctx, "ret ");
|
||||
format_node_ref_or_value(ctx, node->data.ret.ret_val);
|
||||
format_ref_or_value(ctx, value->data.ret.ret_val);
|
||||
} else {
|
||||
scc_tree_dump_append(ctx->dump_ctx, "ret void");
|
||||
}
|
||||
break;
|
||||
case SCC_IR_VALUE_TAG_FUNC_ARG_REF:
|
||||
scc_tree_dump_append_fmt(ctx->dump_ctx, "arg[%zu]",
|
||||
node->data.arg_ref.idx);
|
||||
value->data.arg_ref.idx);
|
||||
break;
|
||||
case SCC_IR_VALUE_TAG_GLOBAL_ALLOC:
|
||||
scc_tree_dump_append_fmt(ctx->dump_ctx, "global %s\n", node->name);
|
||||
scc_ir_dump_node_linear(ctx, node->data.global_alloc.value);
|
||||
scc_tree_dump_append_fmt(ctx->dump_ctx, "global %s\n", value->name);
|
||||
scc_ir_dump_value_linear(ctx, value->data.global_alloc.value);
|
||||
return;
|
||||
case SCC_IR_VALUE_TAG_CONST_ARRAY:
|
||||
scc_tree_dump_append(ctx->dump_ctx, "const_array ");
|
||||
scc_ir_dump_type_linear(ctx, node->data.const_array.base_type);
|
||||
scc_ir_dump_type_linear(ctx, value->data.const_array.base_type);
|
||||
scc_tree_dump_append(ctx->dump_ctx, " [");
|
||||
scc_vec_foreach(node->data.const_array.elements, i) {
|
||||
u8 ch = scc_vec_at(node->data.const_array.elements, i);
|
||||
scc_vec_foreach(value->data.const_array.elements, i) {
|
||||
u8 ch = scc_vec_at(value->data.const_array.elements, i);
|
||||
scc_tree_dump_append_fmt(ctx->dump_ctx, " `%c`, ", ch ? ch : ' ');
|
||||
}
|
||||
scc_tree_dump_append(ctx->dump_ctx, " ]");
|
||||
break;
|
||||
default:
|
||||
scc_tree_dump_append_fmt(ctx->dump_ctx, "<%s node %u>",
|
||||
get_node_type_str(node->tag), node_ref);
|
||||
scc_tree_dump_append_fmt(ctx->dump_ctx, "<%s value %u>",
|
||||
get_node_type_str(value->tag), value_ref);
|
||||
break;
|
||||
}
|
||||
}
|
||||
@@ -613,7 +644,7 @@ void scc_ir_dump_bblock_linear(scc_ir_dump_ctx_t *ctx,
|
||||
for (usize i = 0; i < scc_vec_size(bblock->instrs); i++) {
|
||||
scc_tree_dump_begin_line(ctx->dump_ctx);
|
||||
scc_tree_dump_append(ctx->dump_ctx, " ");
|
||||
scc_ir_dump_node_linear(ctx, scc_vec_at(bblock->instrs, i));
|
||||
scc_ir_dump_value_linear(ctx, scc_vec_at(bblock->instrs, i));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -668,7 +699,7 @@ void scc_ir_dump_func_linear(scc_ir_dump_ctx_t *ctx, scc_ir_func_ref_t func_ref,
|
||||
|
||||
void scc_ir_dump_cprog_linear(scc_ir_dump_ctx_t *ctx) {
|
||||
for (usize i = 0; i < scc_vec_size(ctx->cprog->global_vals); i++) {
|
||||
scc_ir_dump_node_linear(ctx, scc_vec_at(ctx->cprog->global_vals, i));
|
||||
scc_ir_dump_value_linear(ctx, scc_vec_at(ctx->cprog->global_vals, i));
|
||||
}
|
||||
for (usize i = 0; i < scc_vec_size(ctx->cprog->func_decls); i++) {
|
||||
scc_ir_func_ref_t func_decl = scc_vec_at(ctx->cprog->func_decls, i);
|
||||
|
||||
@@ -99,39 +99,39 @@ scc_ir_func_ref_t scc_ir_module_add_func(scc_ir_module_t *ctx,
|
||||
scc_ir_type_t *scc_ir_module_get_type(scc_ir_module_t *ctx,
|
||||
scc_ir_type_ref_t ref) {
|
||||
if (ref == 0)
|
||||
return null;
|
||||
return nullptr;
|
||||
usize idx = GET_ENTITY_INDEX(ctx, ref, uid2type);
|
||||
if (idx >= ctx->types.size)
|
||||
return null;
|
||||
return nullptr;
|
||||
return &ctx->types.data[idx];
|
||||
}
|
||||
|
||||
scc_ir_value_t *scc_ir_module_get_value(scc_ir_module_t *ctx,
|
||||
scc_ir_value_ref_t ref) {
|
||||
if (ref == 0)
|
||||
return null;
|
||||
return nullptr;
|
||||
usize idx = GET_ENTITY_INDEX(ctx, ref, uid2value);
|
||||
if (idx >= ctx->values.size)
|
||||
return null;
|
||||
return nullptr;
|
||||
return &ctx->values.data[idx];
|
||||
}
|
||||
|
||||
scc_ir_bblock_t *scc_ir_module_get_bblock(scc_ir_module_t *ctx,
|
||||
scc_ir_bblock_ref_t ref) {
|
||||
if (ref == 0)
|
||||
return null;
|
||||
return nullptr;
|
||||
usize idx = GET_ENTITY_INDEX(ctx, ref, uid2bblock);
|
||||
if (idx >= ctx->bblocks.size)
|
||||
return null;
|
||||
return nullptr;
|
||||
return &ctx->bblocks.data[idx];
|
||||
}
|
||||
|
||||
scc_ir_func_t *scc_ir_module_get_func(scc_ir_module_t *ctx,
|
||||
scc_ir_func_ref_t ref) {
|
||||
if (ref == 0)
|
||||
return null;
|
||||
return nullptr;
|
||||
usize idx = GET_ENTITY_INDEX(ctx, ref, uid2func);
|
||||
if (idx >= ctx->funcs.size)
|
||||
return null;
|
||||
return nullptr;
|
||||
return &ctx->funcs.data[idx];
|
||||
}
|
||||
|
||||
@@ -1,9 +1,9 @@
|
||||
#include <scc_ir.h>
|
||||
|
||||
void scc_ir_type_init(scc_ir_type_t *in, scc_ir_type_tag_t tag) {
|
||||
Assert(in != null);
|
||||
Assert(in != nullptr);
|
||||
in->tag = tag;
|
||||
in->name = null;
|
||||
in->name = nullptr;
|
||||
switch (tag) {
|
||||
case SCC_IR_TYPE_unknown:
|
||||
case SCC_IR_TYPE_void:
|
||||
@@ -40,31 +40,33 @@ void scc_ir_type_init(scc_ir_type_t *in, scc_ir_type_tag_t tag) {
|
||||
}
|
||||
|
||||
void scc_ir_bblock_init(scc_ir_bblock_t *in, const char *label) {
|
||||
Assert(in != null);
|
||||
Assert(label != null);
|
||||
Assert(in != nullptr);
|
||||
Assert(label != nullptr);
|
||||
in->label = label;
|
||||
scc_vec_init(in->instrs);
|
||||
}
|
||||
|
||||
void scc_ir_func_init(scc_ir_func_t *in, const char *name) {
|
||||
Assert(in != null);
|
||||
Assert(name != null);
|
||||
Assert(in != nullptr);
|
||||
Assert(name != nullptr);
|
||||
in->name = name;
|
||||
in->type = 0;
|
||||
scc_vec_init(in->bblocks);
|
||||
scc_vec_init(in->params);
|
||||
}
|
||||
|
||||
void scc_ir_node_init(scc_ir_value_t *in, const char *name,
|
||||
scc_ir_value_tag_t tag) {
|
||||
Assert(in != null);
|
||||
void scc_ir_value_init(scc_ir_value_t *in, const char *name,
|
||||
scc_ir_value_tag_t tag) {
|
||||
Assert(in != nullptr);
|
||||
in->name = name;
|
||||
in->tag = tag;
|
||||
scc_vec_init(in->used_by);
|
||||
in->type = 0;
|
||||
|
||||
switch (tag) {
|
||||
case SCC_IR_VALUE_TAG_NULL:
|
||||
case SCC_IR_VALUE_TAG_NULLPTR:
|
||||
break;
|
||||
case SCC_IR_VALUE_TAG_BUILTIN:
|
||||
break;
|
||||
case SCC_IR_VALUE_TAG_CONST_INT:
|
||||
// TODO
|
||||
|
||||
3
libs/ir2mcode/include/type_manager.h
Normal file
3
libs/ir2mcode/include/type_manager.h
Normal file
@@ -0,0 +1,3 @@
|
||||
|
||||
#include <scc_ir.h>
|
||||
int scc_ir2mcode_type_width(scc_ir_module_t *ctx, scc_ir_type_t *type);
|
||||
@@ -0,0 +1,50 @@
|
||||
// frame_manager.c
|
||||
#include "frame_manager.h"
|
||||
#include <assert.h>
|
||||
#include <stdlib.h>
|
||||
|
||||
struct frame_manager {
|
||||
int shadow_space; // 影子空间大小(字节)
|
||||
int saved_reg_size; // 已分配的保存寄存器区域大小
|
||||
int local_size; // 已分配的局部变量区域大小
|
||||
int align; // 栈对齐要求
|
||||
};
|
||||
|
||||
void frame_manager_init(frame_manager_t *fm, int shadow_space, int align) {
|
||||
fm->shadow_space = shadow_space;
|
||||
fm->saved_reg_size = 0;
|
||||
fm->local_size = 0;
|
||||
fm->align = align;
|
||||
}
|
||||
|
||||
int frame_alloc_slot(frame_manager_t *fm, int size) {
|
||||
int offset = fm->local_size;
|
||||
fm->local_size += size;
|
||||
return offset; // 返回虚拟偏移(从0开始)
|
||||
}
|
||||
|
||||
int frame_alloc_saved_reg(frame_manager_t *fm, int reg_width) {
|
||||
int offset = fm->saved_reg_size;
|
||||
fm->saved_reg_size += reg_width;
|
||||
return offset;
|
||||
}
|
||||
|
||||
int frame_total_size(frame_manager_t *fm) {
|
||||
int total = fm->shadow_space + fm->saved_reg_size + fm->local_size;
|
||||
// 对齐到 align 字节
|
||||
return (total + fm->align - 1) & ~(fm->align - 1);
|
||||
}
|
||||
|
||||
int frame_slot_offset(frame_manager_t *fm, int slot_idx) {
|
||||
// 布局: RBP 指向保存的 RBP,向下依次是:
|
||||
// [影子空间] [保存寄存器区] [局部变量区]
|
||||
// 局部变量区的起始地址 = RBP - (8 + shadow_space + saved_reg_size)
|
||||
// 其中 8 是 push rbp 占用的空间(返回地址在 RBP+8,但 RBP 本身指向保存的
|
||||
// RBP)
|
||||
int base = 8 + fm->shadow_space + fm->saved_reg_size;
|
||||
return base + slot_idx; // 返回正数,表示从 RBP 向下的字节数
|
||||
}
|
||||
|
||||
int frame_shadow_space(frame_manager_t *fm) { return fm->shadow_space; }
|
||||
|
||||
int frame_saved_reg_size(frame_manager_t *fm) { return fm->saved_reg_size; }
|
||||
|
||||
@@ -2,22 +2,10 @@
|
||||
#include <amd64/scc_amd64_abi.h>
|
||||
#include <reg_alloc.h>
|
||||
#include <scc_ir2mcode.h>
|
||||
#include <type_manager.h>
|
||||
|
||||
#define GET_MODULE(ctx) (&(ctx->cprog->module))
|
||||
|
||||
static int scc_type_width(scc_ir_type_t *type) {
|
||||
/* clang-format off */
|
||||
switch (type->tag) {
|
||||
case SCC_IR_TYPE_i8: case SCC_IR_TYPE_u8: return 1;
|
||||
case SCC_IR_TYPE_i16: case SCC_IR_TYPE_u16: return 2;
|
||||
case SCC_IR_TYPE_i32: case SCC_IR_TYPE_u32: return 4;
|
||||
case SCC_IR_TYPE_i64: case SCC_IR_TYPE_u64: return 8;
|
||||
case SCC_IR_TYPE_PTR: return 8;
|
||||
default: return 8; // 默认64位
|
||||
}
|
||||
/* clang-format on */
|
||||
}
|
||||
|
||||
static bool scc_type_is_signed(scc_ir_type_t *type) {
|
||||
return (type->tag == SCC_IR_TYPE_i8 || type->tag == SCC_IR_TYPE_i16 ||
|
||||
type->tag == SCC_IR_TYPE_i32 || type->tag == SCC_IR_TYPE_i64);
|
||||
@@ -25,9 +13,9 @@ static bool scc_type_is_signed(scc_ir_type_t *type) {
|
||||
|
||||
static void parse_location(scc_ir2mcode_ctx_t *ctx, scc_reg_loc_t *loc,
|
||||
scc_ir_value_ref_t node_ref) {
|
||||
Assert(ctx != null && loc != null);
|
||||
Assert(ctx != nullptr && loc != nullptr);
|
||||
scc_ir_value_t *node = scc_ir_module_get_value(GET_MODULE(ctx), node_ref);
|
||||
if (node == null) {
|
||||
if (node == nullptr) {
|
||||
LOG_FATAL("invalid node ref");
|
||||
UNREACHABLE();
|
||||
return;
|
||||
@@ -140,7 +128,7 @@ typedef SCC_VEC(patch_t) patch_vec_t;
|
||||
static void parse_value(scc_ir2mcode_ctx_t *ctx, scc_ir_bblock_ref_t node_ref,
|
||||
patch_vec_t *patches) {
|
||||
scc_ir_value_t *node = scc_ir_module_get_value(GET_MODULE(ctx), node_ref);
|
||||
if (node == null) {
|
||||
if (node == nullptr) {
|
||||
LOG_ERROR("invalid node ref");
|
||||
return;
|
||||
}
|
||||
@@ -172,7 +160,7 @@ static void parse_value(scc_ir2mcode_ctx_t *ctx, scc_ir_bblock_ref_t node_ref,
|
||||
GET_MODULE(ctx), node->data.load.target);
|
||||
scc_ir_type_t *base_type = scc_ir_module_get_type(
|
||||
GET_MODULE(ctx), ptr_type->data.pointer.base);
|
||||
int width = scc_type_width(base_type);
|
||||
int width = scc_ir2mcode_type_width(GET_MODULE(ctx), base_type);
|
||||
bool is_signed = scc_type_is_signed(base_type);
|
||||
|
||||
// 间接加载到 RAX
|
||||
@@ -202,7 +190,9 @@ static void parse_value(scc_ir2mcode_ctx_t *ctx, scc_ir_bblock_ref_t node_ref,
|
||||
scc_mcode_amd64_mov_r64_m64(&ctx->sect_mcode, SCC_AMD64_RAX,
|
||||
SCC_AMD64_RCX);
|
||||
} else {
|
||||
UNREACHABLE();
|
||||
LOG_WARN("unsupported type width: %d", width);
|
||||
scc_mcode_amd64_mov_r64_m64(&ctx->sect_mcode, SCC_AMD64_RAX,
|
||||
SCC_AMD64_RCX);
|
||||
}
|
||||
// 存储结果
|
||||
store_value_from_reg(&ctx->sect_mcode, &to, SCC_AMD64_RAX);
|
||||
@@ -224,7 +214,7 @@ static void parse_value(scc_ir2mcode_ctx_t *ctx, scc_ir_bblock_ref_t node_ref,
|
||||
GET_MODULE(ctx), node->data.store.target);
|
||||
scc_ir_type_t *base_type = scc_ir_module_get_type(
|
||||
GET_MODULE(ctx), ptr_type->data.pointer.base);
|
||||
int width = scc_type_width(base_type);
|
||||
int width = scc_ir2mcode_type_width(GET_MODULE(ctx), base_type);
|
||||
|
||||
// 根据宽度生成存储指令
|
||||
if (width == 1) {
|
||||
@@ -242,30 +232,47 @@ static void parse_value(scc_ir2mcode_ctx_t *ctx, scc_ir_bblock_ref_t node_ref,
|
||||
}
|
||||
break;
|
||||
}
|
||||
///< 获取指针
|
||||
///< 获取指针
|
||||
case SCC_IR_VALUE_TAG_GET_PTR: {
|
||||
scc_reg_loc_t loc;
|
||||
scc_reg_loc_t loc_res;
|
||||
parse_location(ctx, &loc_res, node_ref);
|
||||
|
||||
scc_ir_value_t *src_addr = scc_ir_module_get_value(
|
||||
GET_MODULE(ctx), node->data.get_ptr.src_addr);
|
||||
Assert(src_addr != null);
|
||||
if (src_addr->tag != SCC_IR_VALUE_TAG_GLOBAL_ALLOC) {
|
||||
Panic();
|
||||
Assert(src_addr != nullptr);
|
||||
|
||||
if (src_addr->tag == SCC_IR_VALUE_TAG_GLOBAL_ALLOC) {
|
||||
// 全局变量:RIP相对寻址
|
||||
scc_mcode_amd64_lea_r64_rip_rel32(&ctx->sect_mcode, SCC_AMD64_RAX,
|
||||
0);
|
||||
usize sym_idx =
|
||||
sccf_builder_get_symbol_idx(ctx->builder, src_addr->name);
|
||||
Assert(sym_idx != 0);
|
||||
sccf_builder_add_reloc(
|
||||
ctx->builder,
|
||||
(sccf_reloc_t){
|
||||
.reloc_type = SCCF_RELOC_TYPE_REL,
|
||||
.offset = scc_vec_size(ctx->sect_mcode.mcode) - 4,
|
||||
.addend = 4,
|
||||
.sect_type = SCCF_SECT_DATA,
|
||||
.sym_idx = sym_idx,
|
||||
});
|
||||
} else if (src_addr->tag == SCC_IR_VALUE_TAG_ALLOC) {
|
||||
// 栈上变量:地址为 rbp - offset
|
||||
scc_reg_loc_t src_loc;
|
||||
parse_location(ctx, &src_loc, node->data.get_ptr.src_addr);
|
||||
// src_loc.kind 应为 SCC_REG_KIND_STACK_ADDR,idx 是虚拟偏移(正数)
|
||||
scc_mcode_amd64_lea_r64_m64_disp32(&ctx->sect_mcode, SCC_AMD64_RAX,
|
||||
SCC_AMD64_RBP, -src_loc.idx - 8);
|
||||
} else {
|
||||
// 其他情况(如链式 getptr):源地址值已经存储在某个位置,直接加载到
|
||||
// RAX
|
||||
scc_reg_loc_t src_loc;
|
||||
parse_location(ctx, &src_loc, node->data.get_ptr.src_addr);
|
||||
load_value_to_reg(&ctx->sect_mcode, &src_loc, SCC_AMD64_RAX);
|
||||
}
|
||||
|
||||
scc_mcode_amd64_lea_r64_rip_rel32(&ctx->sect_mcode, SCC_AMD64_RAX, 0);
|
||||
usize sym_idx =
|
||||
sccf_builder_get_symbol_idx(ctx->builder, src_addr->name);
|
||||
Assert(sym_idx != 0);
|
||||
sccf_builder_add_reloc(
|
||||
ctx->builder, (sccf_reloc_t){
|
||||
.reloc_type = SCCF_RELOC_TYPE_REL,
|
||||
.offset = scc_vec_size(ctx->sect_mcode.mcode) - 4,
|
||||
.addend = 4,
|
||||
.sect_type = SCCF_SECT_DATA,
|
||||
.sym_idx = sym_idx,
|
||||
});
|
||||
parse_location(ctx, &loc, node_ref);
|
||||
store_value_from_reg(&ctx->sect_mcode, &loc, SCC_AMD64_RAX);
|
||||
store_value_from_reg(&ctx->sect_mcode, &loc_res, SCC_AMD64_RAX);
|
||||
break;
|
||||
}
|
||||
case SCC_IR_VALUE_TAG_GET_ELEM_PTR: ///< 获取元素指针(used by array)
|
||||
@@ -555,7 +562,7 @@ static void parse_function(scc_ir2mcode_ctx_t *ctx, scc_ir_func_t *func) {
|
||||
scc_ir_bblock_t *bblock =
|
||||
scc_ir_module_get_bblock(GET_MODULE(ctx), bblock_ref);
|
||||
|
||||
if (bblock == null) {
|
||||
if (bblock == nullptr) {
|
||||
LOG_FATAL("<invalid block>\n");
|
||||
return;
|
||||
}
|
||||
@@ -593,7 +600,7 @@ void scc_ir2amd64(scc_ir2mcode_ctx_t *ctx) {
|
||||
Assert(galloc->tag == SCC_IR_VALUE_TAG_GLOBAL_ALLOC);
|
||||
scc_ir_value_t *value = scc_ir_module_get_value(
|
||||
GET_MODULE(ctx), galloc->data.global_alloc.value);
|
||||
Assert(value != null);
|
||||
Assert(value != nullptr);
|
||||
sccf_sym_t sym = (sccf_sym_t){
|
||||
.sccf_sect_offset = scc_vec_size(ctx->sect_data),
|
||||
.sccf_sect_type = SCCF_SECT_DATA,
|
||||
@@ -654,7 +661,7 @@ void scc_ir2amd64(scc_ir2mcode_ctx_t *ctx) {
|
||||
}
|
||||
sccf_sym_t *sym =
|
||||
sccf_builder_get_symbol_unsafe(ctx->builder, func->name);
|
||||
Assert(sym != null);
|
||||
Assert(sym != nullptr);
|
||||
sym->sccf_sect_offset = scc_vec_size(ctx->sect_mcode.mcode);
|
||||
parse_function(ctx, func);
|
||||
}
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
#include "reg_alloc.h"
|
||||
#include <reg_alloc.h>
|
||||
#include <type_manager.h>
|
||||
|
||||
u32 hash_func(const void *key) { return (usize)key; }
|
||||
int equal_func(const void *key1, const void *key2) {
|
||||
@@ -39,12 +40,12 @@ scc_hashtable_t *scc_reg_alloc_with_stack(scc_reg_alloc_t *ctx,
|
||||
scc_ir_bblock_ref_t bblock_ref = scc_vec_at(func->bblocks, i);
|
||||
scc_ir_bblock_t *bblock =
|
||||
scc_ir_module_get_bblock(ctx->ir_module, bblock_ref);
|
||||
Assert(bblock != null);
|
||||
Assert(bblock != nullptr);
|
||||
scc_vec_foreach(bblock->instrs, j) {
|
||||
scc_ir_value_ref_t node_ref = scc_vec_at(bblock->instrs, j);
|
||||
scc_ir_value_t *node =
|
||||
scc_ir_module_get_value(ctx->ir_module, node_ref);
|
||||
Assert(node != null);
|
||||
Assert(node != nullptr);
|
||||
loc.kind = SCC_REG_KIND_UNDEF;
|
||||
switch (node->tag) {
|
||||
case SCC_IR_VALUE_TAG_LOAD:
|
||||
@@ -65,8 +66,17 @@ scc_hashtable_t *scc_reg_alloc_with_stack(scc_reg_alloc_t *ctx,
|
||||
// 为 alloc 分配栈偏移,但不作为普通值存储
|
||||
loc.kind =
|
||||
SCC_REG_KIND_STACK_ADDR; // 实际不需要存储到 reg_loc_vec
|
||||
scc_ir_type_t *type =
|
||||
scc_ir_module_get_type(ctx->ir_module, node->type);
|
||||
Assert(type != nullptr);
|
||||
loc.idx = ctx->alloc_stack_size;
|
||||
ctx->alloc_stack_size += 8; // 根据类型大小调整
|
||||
Assert(type->tag == SCC_IR_TYPE_PTR);
|
||||
int len = scc_ir2mcode_type_width(
|
||||
ctx->ir_module,
|
||||
scc_ir_module_get_type(ctx->ir_module,
|
||||
type->data.pointer.base));
|
||||
len = len % 8 == 0 ? len : len + 8 - len % 8;
|
||||
ctx->alloc_stack_size += len;
|
||||
|
||||
// 记录偏移
|
||||
scc_vec_push(ctx->reg_loc_vec, loc);
|
||||
|
||||
23
libs/ir2mcode/src/type_manager.c
Normal file
23
libs/ir2mcode/src/type_manager.c
Normal file
@@ -0,0 +1,23 @@
|
||||
#include <type_manager.h>
|
||||
|
||||
int scc_ir2mcode_type_width(scc_ir_module_t *ctx, scc_ir_type_t *type) {
|
||||
/* clang-format off */
|
||||
if (ctx == nullptr || type == nullptr) {
|
||||
Panic("Invalid argument");
|
||||
return 0;
|
||||
}
|
||||
switch (type->tag) {
|
||||
case SCC_IR_TYPE_i8: case SCC_IR_TYPE_u8: return 1;
|
||||
case SCC_IR_TYPE_i16: case SCC_IR_TYPE_u16: return 2;
|
||||
case SCC_IR_TYPE_i32: case SCC_IR_TYPE_u32: return 4;
|
||||
case SCC_IR_TYPE_i64: case SCC_IR_TYPE_u64: return 8;
|
||||
case SCC_IR_TYPE_PTR: return 8;
|
||||
case SCC_IR_TYPE_ARRAY:
|
||||
return scc_ir2mcode_type_width(
|
||||
ctx,
|
||||
scc_ir_module_get_type(ctx, type->data.array.base)
|
||||
) * type->data.array.len;
|
||||
default: return 8; // 默认64位
|
||||
}
|
||||
/* clang-format on */
|
||||
}
|
||||
@@ -24,7 +24,7 @@ void test_example(const char *input, cbool need_sema, const char *name) {
|
||||
scc_sema_init(&sema_callbacks);
|
||||
scc_parser_init(&parser, tok_ring, &sema_callbacks);
|
||||
} else {
|
||||
scc_parser_init(&parser, tok_ring, null);
|
||||
scc_parser_init(&parser, tok_ring, nullptr);
|
||||
}
|
||||
|
||||
scc_ast_translation_unit_t *tu = scc_parse_translation_unit(&parser);
|
||||
|
||||
@@ -193,11 +193,11 @@ scc_tok_subtype_t scc_get_tok_subtype(scc_tok_type_t type);
|
||||
const char *scc_get_tok_name(scc_tok_type_t type);
|
||||
|
||||
static inline void scc_lexer_tok_drop(scc_lexer_tok_t *tok) {
|
||||
Assert(tok != null);
|
||||
Assert(tok != nullptr);
|
||||
tok->type = SCC_TOK_UNKNOWN;
|
||||
tok->loc.col = 0;
|
||||
tok->loc.line = 0;
|
||||
tok->loc.name = null;
|
||||
tok->loc.name = nullptr;
|
||||
tok->loc.offset = 0;
|
||||
scc_str_drop(&tok->lexeme);
|
||||
}
|
||||
@@ -209,7 +209,7 @@ static inline cbool scc_lexer_tok_match(const scc_lexer_tok_t *tok,
|
||||
|
||||
// 深拷贝 token
|
||||
static inline scc_lexer_tok_t scc_lexer_tok_copy(const scc_lexer_tok_t *src) {
|
||||
Assert(src != null);
|
||||
Assert(src != nullptr);
|
||||
scc_lexer_tok_t dst = *src;
|
||||
dst.lexeme = scc_str_copy(&src->lexeme);
|
||||
return dst;
|
||||
@@ -218,9 +218,9 @@ static inline scc_lexer_tok_t scc_lexer_tok_copy(const scc_lexer_tok_t *src) {
|
||||
// 移动 token(源 token 不再拥有 lexeme)
|
||||
static inline void scc_lexer_tok_move(scc_lexer_tok_t *dst,
|
||||
scc_lexer_tok_t *src) {
|
||||
Assert(src != null);
|
||||
Assert(src != nullptr);
|
||||
*dst = *src;
|
||||
src->lexeme.data = null;
|
||||
src->lexeme.data = nullptr;
|
||||
src->lexeme.size = 0;
|
||||
src->lexeme.cap = 0;
|
||||
}
|
||||
|
||||
@@ -4,13 +4,13 @@
|
||||
#include "scc_lexer.h"
|
||||
|
||||
static inline void scc_lexer_gen_number_true(scc_lexer_tok_t *tok) {
|
||||
Assert(tok != null && tok->type == SCC_TOK_UNKNOWN);
|
||||
Assert(tok != nullptr && tok->type == SCC_TOK_UNKNOWN);
|
||||
tok->type = SCC_TOK_INT_LITERAL;
|
||||
tok->lexeme = scc_str_from_cstr("1");
|
||||
}
|
||||
|
||||
static inline void scc_lexer_gen_number_false(scc_lexer_tok_t *tok) {
|
||||
Assert(tok != null && tok->type == SCC_TOK_UNKNOWN);
|
||||
Assert(tok != nullptr && tok->type == SCC_TOK_UNKNOWN);
|
||||
tok->type = SCC_TOK_INT_LITERAL;
|
||||
tok->lexeme = scc_str_from_cstr("0");
|
||||
}
|
||||
|
||||
@@ -538,7 +538,7 @@ void scc_lexer_drop_ring(scc_lexer_tok_ring_t *ring_ref) {
|
||||
}
|
||||
|
||||
void scc_lexer_drop(scc_lexer_t *lexer) {
|
||||
Assert(lexer != null);
|
||||
Assert(lexer != nullptr);
|
||||
if (lexer->ring_ref_count) {
|
||||
LOG_FATAL("drop sstream must be drop ring before ref [%d]",
|
||||
lexer->ring_ref_count);
|
||||
|
||||
@@ -24,12 +24,12 @@ int g_num_arr[3];
|
||||
int main(int argc, char *argv[]) {
|
||||
// int num = 0;
|
||||
if (argc == 3 && strcmp(argv[2], "--debug") == 0) {
|
||||
log_set_level(NULL, LOG_LEVEL_ALL);
|
||||
log_set_level(nullptr, LOG_LEVEL_ALL);
|
||||
} else {
|
||||
// FIXME it is a hack lexer_logger
|
||||
log_set_level(&__scc_lexer_log, LOG_LEVEL_NOTSET);
|
||||
log_set_level(NULL, LOG_LEVEL_INFO | LOG_LEVEL_WARN | LOG_LEVEL_ERROR |
|
||||
LOG_LEVEL_FATAL);
|
||||
log_set_level(nullptr, LOG_LEVEL_INFO | LOG_LEVEL_WARN |
|
||||
LOG_LEVEL_ERROR | LOG_LEVEL_FATAL);
|
||||
}
|
||||
|
||||
const char *file_name = __FILE__;
|
||||
|
||||
@@ -412,5 +412,5 @@ TEST_LIST = {
|
||||
{"edge_cases", test_edge_cases},
|
||||
{"sequences", test_sequences},
|
||||
{"error_recovery", test_error_recovery},
|
||||
{NULL, NULL},
|
||||
{nullptr, nullptr},
|
||||
};
|
||||
@@ -794,6 +794,138 @@ SCC_MCODE_FUNC void scc_mcode_amd64_movzx_r64_r16(scc_mcode_t *mcode, int dst,
|
||||
scc_mcode_add_u8(mcode, modrm);
|
||||
}
|
||||
|
||||
// ==================== 符号/零扩展加载(内存操作数) ====================
|
||||
|
||||
/**
|
||||
* @brief 从内存加载字节并符号扩展到 64 位 (movsx r64, byte ptr [base])
|
||||
*
|
||||
* @param mcode 机器码缓冲区
|
||||
* @param dst 目标 64 位寄存器
|
||||
* @param base 基址寄存器(存储地址)
|
||||
*/
|
||||
SCC_MCODE_FUNC void scc_mcode_amd64_movsx_r64_m8(scc_mcode_t *mcode, int dst,
|
||||
int base) {
|
||||
u8 rex = 0x48; // REX.W = 1
|
||||
if (dst >= 8)
|
||||
rex |= 0x04; // REX.R
|
||||
if (base >= 8)
|
||||
rex |= 0x01; // REX.B
|
||||
scc_mcode_add_u8(mcode, rex);
|
||||
scc_mcode_add_u8(mcode, 0x0F);
|
||||
scc_mcode_add_u8(mcode, 0xBE); // MOVSX r64, r/m8
|
||||
u8 modrm = 0x00 | ((dst & 7) << 3) | (base & 7);
|
||||
if ((base & 7) == 4) {
|
||||
// 需要 SIB 字节 (base == RSP 或 R12)
|
||||
scc_mcode_add_u8(mcode, modrm);
|
||||
scc_mcode_add_u8(mcode, 0x24); // SIB: [base] 无索引,base=4
|
||||
} else {
|
||||
scc_mcode_add_u8(mcode, modrm);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief 从内存加载字节并零扩展到 64 位 (movzx r64, byte ptr [base])
|
||||
*
|
||||
* @param mcode 机器码缓冲区
|
||||
* @param dst 目标 64 位寄存器
|
||||
* @param base 基址寄存器
|
||||
*/
|
||||
SCC_MCODE_FUNC void scc_mcode_amd64_movzx_r64_m8(scc_mcode_t *mcode, int dst,
|
||||
int base) {
|
||||
u8 rex = 0x48;
|
||||
if (dst >= 8)
|
||||
rex |= 0x04;
|
||||
if (base >= 8)
|
||||
rex |= 0x01;
|
||||
scc_mcode_add_u8(mcode, rex);
|
||||
scc_mcode_add_u8(mcode, 0x0F);
|
||||
scc_mcode_add_u8(mcode, 0xB6); // MOVZX r64, r/m8
|
||||
u8 modrm = 0x00 | ((dst & 7) << 3) | (base & 7);
|
||||
if ((base & 7) == 4) {
|
||||
scc_mcode_add_u8(mcode, modrm);
|
||||
scc_mcode_add_u8(mcode, 0x24);
|
||||
} else {
|
||||
scc_mcode_add_u8(mcode, modrm);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief 从内存加载16位并符号扩展到 64 位 (movsx r64, word ptr [base])
|
||||
*
|
||||
* @param mcode 机器码缓冲区
|
||||
* @param dst 目标 64 位寄存器
|
||||
* @param base 基址寄存器
|
||||
*/
|
||||
SCC_MCODE_FUNC void scc_mcode_amd64_movsx_r64_m16(scc_mcode_t *mcode, int dst,
|
||||
int base) {
|
||||
u8 rex = 0x48;
|
||||
if (dst >= 8)
|
||||
rex |= 0x04;
|
||||
if (base >= 8)
|
||||
rex |= 0x01;
|
||||
scc_mcode_add_u8(mcode, rex);
|
||||
scc_mcode_add_u8(mcode, 0x0F);
|
||||
scc_mcode_add_u8(mcode, 0xBF); // MOVSX r64, r/m16
|
||||
u8 modrm = 0x00 | ((dst & 7) << 3) | (base & 7);
|
||||
if ((base & 7) == 4) {
|
||||
scc_mcode_add_u8(mcode, modrm);
|
||||
scc_mcode_add_u8(mcode, 0x24);
|
||||
} else {
|
||||
scc_mcode_add_u8(mcode, modrm);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief 从内存加载16位并零扩展到 64 位 (movzx r64, word ptr [base])
|
||||
*
|
||||
* @param mcode 机器码缓冲区
|
||||
* @param dst 目标 64 位寄存器
|
||||
* @param base 基址寄存器
|
||||
*/
|
||||
SCC_MCODE_FUNC void scc_mcode_amd64_movzx_r64_m16(scc_mcode_t *mcode, int dst,
|
||||
int base) {
|
||||
u8 rex = 0x48;
|
||||
if (dst >= 8)
|
||||
rex |= 0x04;
|
||||
if (base >= 8)
|
||||
rex |= 0x01;
|
||||
scc_mcode_add_u8(mcode, rex);
|
||||
scc_mcode_add_u8(mcode, 0x0F);
|
||||
scc_mcode_add_u8(mcode, 0xB7); // MOVZX r64, r/m16
|
||||
u8 modrm = 0x00 | ((dst & 7) << 3) | (base & 7);
|
||||
if ((base & 7) == 4) {
|
||||
scc_mcode_add_u8(mcode, modrm);
|
||||
scc_mcode_add_u8(mcode, 0x24);
|
||||
} else {
|
||||
scc_mcode_add_u8(mcode, modrm);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief 从内存加载32位并符号扩展到 64 位 (movsxd r64, dword ptr [base])
|
||||
*
|
||||
* @param mcode 机器码缓冲区
|
||||
* @param dst 目标 64 位寄存器
|
||||
* @param base 基址寄存器
|
||||
*/
|
||||
SCC_MCODE_FUNC void scc_mcode_amd64_movsx_r64_m32(scc_mcode_t *mcode, int dst,
|
||||
int base) {
|
||||
u8 rex = 0x48; // REX.W = 1, 对应 MOVSXD
|
||||
if (dst >= 8)
|
||||
rex |= 0x04;
|
||||
if (base >= 8)
|
||||
rex |= 0x01;
|
||||
scc_mcode_add_u8(mcode, rex);
|
||||
scc_mcode_add_u8(mcode, 0x63); // MOVSXD r64, r/m32
|
||||
u8 modrm = 0x00 | ((dst & 7) << 3) | (base & 7);
|
||||
if ((base & 7) == 4) {
|
||||
scc_mcode_add_u8(mcode, modrm);
|
||||
scc_mcode_add_u8(mcode, 0x24);
|
||||
} else {
|
||||
scc_mcode_add_u8(mcode, modrm);
|
||||
}
|
||||
}
|
||||
|
||||
// ==================== 算术运算 ====================
|
||||
|
||||
// ---------- 64 位 ----------
|
||||
@@ -1670,6 +1802,74 @@ SCC_MCODE_FUNC void scc_mcode_amd64_xor_r64_imm32(scc_mcode_t *mcode, int dst,
|
||||
scc_mcode_add_u32(mcode, imm);
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief 64 位按位取反 NOT r64
|
||||
*
|
||||
* @param mcode 机器码缓冲区
|
||||
* @param dst 目标寄存器
|
||||
*/
|
||||
SCC_MCODE_FUNC void scc_mcode_amd64_not_r64(scc_mcode_t *mcode, int dst) {
|
||||
u8 rex = 0x48;
|
||||
if (dst >= 8)
|
||||
rex |= 0x01;
|
||||
scc_mcode_add_u8(mcode, rex);
|
||||
scc_mcode_add_u8(mcode, 0xF7);
|
||||
u8 modrm = 0xC0 | (dst & 7) | (2 << 3); // reg/opcode = 2 for NOT
|
||||
scc_mcode_add_u8(mcode, modrm);
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief 32 位按位取反 NOT r32
|
||||
*
|
||||
* @param mcode 机器码缓冲区
|
||||
* @param dst 目标寄存器
|
||||
*/
|
||||
SCC_MCODE_FUNC void scc_mcode_amd64_not_r32(scc_mcode_t *mcode, int dst) {
|
||||
u8 rex = 0x40; // REX.W=0
|
||||
if (dst >= 8)
|
||||
rex |= 0x01;
|
||||
scc_mcode_add_u8(mcode, rex);
|
||||
scc_mcode_add_u8(mcode, 0xF7);
|
||||
u8 modrm = 0xC0 | (dst & 7) | (2 << 3); // reg/opcode = 2 for NOT
|
||||
scc_mcode_add_u8(mcode, modrm);
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief 16 位按位取反 NOT r16
|
||||
*
|
||||
* @param mcode 机器码缓冲区
|
||||
* @param dst 目标寄存器
|
||||
*/
|
||||
SCC_MCODE_FUNC void scc_mcode_amd64_not_r16(scc_mcode_t *mcode, int dst) {
|
||||
scc_mcode_amd64_emit_width_prefix(mcode, 2);
|
||||
u8 rex = 0x40;
|
||||
if (dst >= 8)
|
||||
rex |= 0x01;
|
||||
scc_mcode_add_u8(mcode, rex);
|
||||
scc_mcode_add_u8(mcode, 0xF7);
|
||||
u8 modrm = 0xC0 | (dst & 7) | (2 << 3); // reg/opcode = 2 for NOT
|
||||
scc_mcode_add_u8(mcode, modrm);
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief 8 位按位取反 NOT r8
|
||||
*
|
||||
* @param mcode 机器码缓冲区
|
||||
* @param dst 目标寄存器
|
||||
*/
|
||||
SCC_MCODE_FUNC void scc_mcode_amd64_not_r8(scc_mcode_t *mcode, int dst) {
|
||||
u8 rex = 0x40;
|
||||
int need_rex = scc_mcode_amd64_is_byte_reg_needs_rex(dst);
|
||||
if (dst >= 8)
|
||||
rex |= 0x01;
|
||||
if (need_rex) {
|
||||
scc_mcode_add_u8(mcode, rex);
|
||||
}
|
||||
scc_mcode_add_u8(mcode, 0xF6); // 8位版本使用0xF6
|
||||
u8 modrm = 0xC0 | (dst & 7) | (2 << 3); // reg/opcode = 2 for NOT
|
||||
scc_mcode_add_u8(mcode, modrm);
|
||||
}
|
||||
|
||||
// ==================== 移位 ====================
|
||||
|
||||
// 提供 64 位示例,其他宽度可类似添加
|
||||
@@ -1873,6 +2073,19 @@ SCC_MCODE_FUNC void scc_mcode_amd64_call_rel32(scc_mcode_t *mcode, u32 rel32) {
|
||||
scc_mcode_add_u32(mcode, rel32);
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief 通过内存地址调用 (call [rip+disp32]) - 通常用于导入表调用
|
||||
*
|
||||
* @param mcode 机器码缓冲区
|
||||
* @param disp 32 位相对偏移
|
||||
*/
|
||||
SCC_MCODE_FUNC void scc_mcode_amd64_call_mem_rip_rel32(scc_mcode_t *mcode,
|
||||
u32 disp) {
|
||||
scc_mcode_add_u8(mcode, 0xFF);
|
||||
scc_mcode_add_u8(mcode, 0x15); // reg=010 (CALL), r/m=101 (RIP+disp32)
|
||||
scc_mcode_add_u32(mcode, disp);
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief 间接跳转 JMP r64
|
||||
*
|
||||
|
||||
@@ -5,20 +5,20 @@
|
||||
|
||||
static inline const scc_lexer_tok_t *scc_parser_peek(scc_parser_t *parser) {
|
||||
cbool ok = false;
|
||||
const scc_lexer_tok_t *tok = null;
|
||||
const scc_lexer_tok_t *tok = nullptr;
|
||||
scc_ring_unsafe_peek_ref(*parser->ring, tok, ok);
|
||||
if (ok == false) {
|
||||
return null;
|
||||
return nullptr;
|
||||
}
|
||||
return tok;
|
||||
}
|
||||
|
||||
static inline const scc_lexer_tok_t *scc_parser_next(scc_parser_t *parser) {
|
||||
cbool ok = false;
|
||||
const scc_lexer_tok_t *tok = null;
|
||||
const scc_lexer_tok_t *tok = nullptr;
|
||||
scc_ring_unsafe_next_ref(*parser->ring, tok, ok);
|
||||
if (ok == false) {
|
||||
return null;
|
||||
return nullptr;
|
||||
}
|
||||
return tok;
|
||||
}
|
||||
@@ -26,10 +26,10 @@ static inline const scc_lexer_tok_t *scc_parser_next(scc_parser_t *parser) {
|
||||
static inline cbool scc_parser_consume_if(scc_parser_t *parser,
|
||||
scc_tok_type_t type) {
|
||||
cbool ok = false;
|
||||
scc_lexer_tok_t *tok = null;
|
||||
scc_lexer_tok_t *tok = nullptr;
|
||||
scc_ring_unsafe_peek_ref(*parser->ring, tok, ok);
|
||||
if (ok == false) {
|
||||
return null;
|
||||
return nullptr;
|
||||
}
|
||||
if (tok->type == type) {
|
||||
scc_lexer_tok_drop(tok);
|
||||
@@ -48,13 +48,13 @@ static inline void scc_parser_restore(scc_parser_t *parser) {
|
||||
_scc_ring_probe(*parser->ring) = parser->checkpoint;
|
||||
}
|
||||
|
||||
// tok can null it will be safty free
|
||||
// tok can nullptr it will be safty free
|
||||
static inline cbool scc_parser_next_consume(scc_parser_t *parser,
|
||||
scc_lexer_tok_t *tok) {
|
||||
cbool ok = false;
|
||||
scc_lexer_tok_t *raw_tok_ref = null;
|
||||
scc_lexer_tok_t *raw_tok_ref = nullptr;
|
||||
scc_ring_unsafe_next_ref_consume(*parser->ring, raw_tok_ref, ok);
|
||||
if (tok == null) {
|
||||
if (tok == nullptr) {
|
||||
scc_lexer_tok_drop(raw_tok_ref);
|
||||
} else {
|
||||
scc_lexer_tok_move(tok, raw_tok_ref);
|
||||
@@ -75,7 +75,7 @@ static inline void scc_parser_reset(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);
|
||||
scc_pos_t pos = scc_pos_create();
|
||||
if (tok != null)
|
||||
if (tok != nullptr)
|
||||
pos = tok->loc;
|
||||
return pos;
|
||||
}
|
||||
|
||||
@@ -27,7 +27,7 @@ typedef struct scc_parser {
|
||||
* @brief 初始化解析器
|
||||
* @param parser 解析器实例
|
||||
* @param lexer 词法分析器实例
|
||||
* @param callbacks 语义分析回调(可为 null)
|
||||
* @param callbacks 语义分析回调(可为 nullptr)
|
||||
*/
|
||||
void scc_parser_init(scc_parser_t *parser, scc_lexer_tok_ring_t *tok_ring,
|
||||
scc_sema_callbacks_t *callbacks);
|
||||
|
||||
@@ -173,10 +173,10 @@ scc_ast_expr_t *scc_parse_initializer(scc_parser_t *parser,
|
||||
[ constant-expression ]
|
||||
. identifier
|
||||
*/
|
||||
const scc_lexer_tok_t *tok_ptr = null;
|
||||
const scc_lexer_tok_t *tok_ptr = nullptr;
|
||||
scc_lexer_tok_t tok = {0};
|
||||
tok_ptr = scc_parser_peek(parser);
|
||||
scc_ast_expr_t *init = null;
|
||||
scc_ast_expr_t *init = nullptr;
|
||||
if (!(tok_ptr && tok_ptr->type == SCC_TOK_L_BRACE)) {
|
||||
// TODO int a = 1, b = 1;
|
||||
init = scc_parse_assignment_expression(parser);
|
||||
@@ -187,23 +187,23 @@ scc_ast_expr_t *scc_parse_initializer(scc_parser_t *parser,
|
||||
scc_lexer_tok_drop(&tok);
|
||||
|
||||
init = scc_malloc(sizeof(scc_ast_expr_t));
|
||||
Assert(init != null);
|
||||
Assert(init != nullptr);
|
||||
scc_ast_expr_vec_t lhs_exprs;
|
||||
scc_vec_init(lhs_exprs);
|
||||
scc_ast_expr_vec_t rhs_exprs;
|
||||
scc_vec_init(rhs_exprs);
|
||||
scc_ast_expr_t *lhs = null;
|
||||
scc_ast_expr_t *rhs = null;
|
||||
scc_ast_expr_t *lhs = nullptr;
|
||||
scc_ast_expr_t *rhs = nullptr;
|
||||
scc_ast_expr_t *ptr = base;
|
||||
while (1) {
|
||||
tok_ptr = scc_parser_peek(parser);
|
||||
if (tok_ptr->type == SCC_TOK_DOT) {
|
||||
scc_parser_next_consume(parser, null);
|
||||
scc_parser_next_consume(parser, nullptr);
|
||||
tok_ptr = scc_parser_peek(parser);
|
||||
if (tok_ptr && tok_ptr->type == SCC_TOK_IDENT) {
|
||||
scc_parser_next_consume(parser, &tok);
|
||||
lhs = scc_malloc(sizeof(scc_ast_expr_t));
|
||||
Assert(lhs != null);
|
||||
Assert(lhs != nullptr);
|
||||
scc_ast_expr_member_init(lhs, ptr, scc_str_as_cstr(&tok.lexeme),
|
||||
tok.loc);
|
||||
if (!scc_parser_consume_if(parser, SCC_TOK_ASSIGN)) {
|
||||
@@ -211,7 +211,7 @@ scc_ast_expr_t *scc_parse_initializer(scc_parser_t *parser,
|
||||
continue;
|
||||
}
|
||||
rhs = scc_parse_initializer(parser, lhs);
|
||||
if (rhs == null) {
|
||||
if (rhs == nullptr) {
|
||||
SCC_ERROR(scc_parser_got_current_pos(parser),
|
||||
"Expected initializer");
|
||||
Panic();
|
||||
@@ -224,34 +224,34 @@ scc_ast_expr_t *scc_parse_initializer(scc_parser_t *parser,
|
||||
"Expected 'identifier' after '.'");
|
||||
}
|
||||
} else if (tok_ptr->type == SCC_TOK_L_BRACKET) {
|
||||
scc_parser_next_consume(parser, null);
|
||||
scc_parser_next_consume(parser, nullptr);
|
||||
scc_ast_expr_t *idx = scc_parser_constant_expression(parser);
|
||||
Assert(idx != null);
|
||||
Assert(idx != nullptr);
|
||||
if (!scc_parser_consume_if(parser, SCC_TOK_R_BRACKET)) {
|
||||
SCC_ERROR(scc_parser_got_current_pos(parser), "Expected ']'");
|
||||
}
|
||||
lhs = scc_malloc(sizeof(scc_ast_expr_t));
|
||||
Assert(lhs != null);
|
||||
Assert(lhs != nullptr);
|
||||
scc_ast_expr_array_subscript_init(lhs, ptr, idx, tok_ptr->loc);
|
||||
if (!scc_parser_consume_if(parser, SCC_TOK_ASSIGN)) {
|
||||
ptr = lhs;
|
||||
continue;
|
||||
}
|
||||
rhs = scc_parse_initializer(parser, lhs);
|
||||
Assert(rhs != null);
|
||||
Assert(rhs != nullptr);
|
||||
scc_vec_push(lhs_exprs, lhs);
|
||||
scc_vec_push(rhs_exprs, rhs);
|
||||
ptr = base;
|
||||
} else if (tok_ptr->type == SCC_TOK_R_BRACE) {
|
||||
scc_parser_next_consume(parser, null);
|
||||
scc_parser_next_consume(parser, nullptr);
|
||||
break;
|
||||
} else if (tok_ptr->type == SCC_TOK_COMMA) {
|
||||
scc_parser_next_consume(parser, null);
|
||||
scc_parser_next_consume(parser, nullptr);
|
||||
continue;
|
||||
} else {
|
||||
// FIXME
|
||||
scc_ast_expr_t *expr = scc_parse_initializer(parser, base);
|
||||
scc_vec_push(lhs_exprs, null);
|
||||
scc_vec_push(lhs_exprs, nullptr);
|
||||
scc_vec_push(rhs_exprs, expr);
|
||||
}
|
||||
}
|
||||
@@ -260,29 +260,29 @@ scc_ast_expr_t *scc_parse_initializer(scc_parser_t *parser,
|
||||
}
|
||||
|
||||
scc_ast_decl_t *scc_parse_declaration(scc_parser_t *parser) {
|
||||
const scc_lexer_tok_t *tok_ptr = null;
|
||||
const scc_lexer_tok_t *tok_ptr = nullptr;
|
||||
|
||||
scc_ast_decl_t *decl_list = null;
|
||||
scc_ast_decl_t *decl_list = nullptr;
|
||||
scc_ast_decl_vec_t decl_list_vec;
|
||||
scc_vec_init(decl_list_vec);
|
||||
|
||||
scc_ast_type_t *type = scc_parse_declaration_specifiers(parser);
|
||||
if (type == null) {
|
||||
return null;
|
||||
if (type == nullptr) {
|
||||
return nullptr;
|
||||
}
|
||||
scc_ast_decl_specifier_t spec = type->quals;
|
||||
// FIXME drop typedef inline and ...
|
||||
type->quals.is_typedef = false;
|
||||
|
||||
scc_ast_decl_t *decl = null;
|
||||
scc_ast_decl_t *decl = nullptr;
|
||||
CONTINUE:
|
||||
decl = scc_parse_declarator(parser, type);
|
||||
if (decl == null) {
|
||||
return null;
|
||||
if (decl == nullptr) {
|
||||
return nullptr;
|
||||
}
|
||||
tok_ptr = scc_parser_peek(parser);
|
||||
if (tok_ptr->type == SCC_TOK_ASSIGN) {
|
||||
scc_parser_next_consume(parser, null);
|
||||
scc_parser_next_consume(parser, nullptr);
|
||||
// TODO maybe memory leak
|
||||
scc_ast_expr_t *lvalue = scc_malloc(sizeof(scc_ast_expr_t));
|
||||
scc_ast_expr_lvalue_init(lvalue, decl->var.type, decl->base.loc);
|
||||
@@ -290,7 +290,7 @@ CONTINUE:
|
||||
} else if (tok_ptr->type == SCC_TOK_L_BRACE) {
|
||||
scc_parse_decl_sema(parser, decl);
|
||||
parser->sema_callbacks.on_decl(parser->sema_callbacks.context,
|
||||
scc_ast_decl_t_BEGIN, null);
|
||||
scc_ast_decl_t_BEGIN, nullptr);
|
||||
scc_vec_foreach(decl->func.type->function.params, i) {
|
||||
scc_ast_decl_t *param =
|
||||
scc_vec_at(decl->func.type->function.params, i);
|
||||
@@ -299,19 +299,19 @@ CONTINUE:
|
||||
}
|
||||
scc_ast_stmt_t *body = scc_parse_statement(parser);
|
||||
parser->sema_callbacks.on_decl(parser->sema_callbacks.context,
|
||||
scc_ast_decl_t_END, null);
|
||||
scc_ast_decl_t_END, nullptr);
|
||||
Assert(decl->base.type == SCC_AST_DECL_FUNC);
|
||||
decl->func.body = body;
|
||||
Assert(decl->func.type != null);
|
||||
Assert(decl->func.type != nullptr);
|
||||
Assert(decl->func.type->base.type == SCC_AST_TYPE_FUNCTION);
|
||||
Assert(decl->func.body != null);
|
||||
Assert(decl->func.body != nullptr);
|
||||
Assert(decl->func.body->base.type == SCC_AST_STMT_COMPOUND);
|
||||
goto RETURN;
|
||||
}
|
||||
|
||||
tok_ptr = scc_parser_peek(parser);
|
||||
if (tok_ptr->type == SCC_TOK_SEMICOLON) {
|
||||
scc_parser_next_consume(parser, null);
|
||||
scc_parser_next_consume(parser, nullptr);
|
||||
if (decl_list)
|
||||
scc_vec_push(decl_list_vec, decl);
|
||||
if (spec.is_typedef) {
|
||||
@@ -326,7 +326,7 @@ CONTINUE:
|
||||
decl->base.loc);
|
||||
}
|
||||
}
|
||||
if (decl_list != null) {
|
||||
if (decl_list != nullptr) {
|
||||
scc_vec_foreach(decl_list_vec, i) {
|
||||
decl = scc_vec_at(decl_list_vec, i);
|
||||
scc_parse_decl_sema(parser, decl);
|
||||
@@ -340,10 +340,10 @@ CONTINUE:
|
||||
}
|
||||
goto RETURN;
|
||||
} else if (tok_ptr->type == SCC_TOK_COMMA) {
|
||||
scc_parser_next_consume(parser, null);
|
||||
if (decl_list == null) {
|
||||
scc_parser_next_consume(parser, nullptr);
|
||||
if (decl_list == nullptr) {
|
||||
decl_list = scc_malloc(sizeof(scc_ast_decl_t));
|
||||
Assert(decl_list != null);
|
||||
Assert(decl_list != nullptr);
|
||||
scc_vec_push(decl_list_vec, decl);
|
||||
} else {
|
||||
Assert(scc_vec_size(decl_list_vec) != 0);
|
||||
@@ -361,5 +361,5 @@ CONTINUE:
|
||||
RETURN:
|
||||
return decl;
|
||||
ERROR:
|
||||
return null;
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
@@ -324,7 +324,7 @@ static scc_ast_expr_op_t map_token_to_assign_op(scc_tok_type_t type) {
|
||||
// 跳过直到遇到同步 token(分号、右括号、逗号、EOF)
|
||||
static void parser_sync(scc_parser_t *parser) {
|
||||
const scc_lexer_tok_t *tok_ptr;
|
||||
while ((tok_ptr = scc_parser_peek(parser)) != null) {
|
||||
while ((tok_ptr = scc_parser_peek(parser)) != nullptr) {
|
||||
scc_tok_type_t type = tok_ptr->type;
|
||||
if (type == SCC_TOK_SEMICOLON || type == SCC_TOK_R_PAREN ||
|
||||
type == SCC_TOK_R_BRACE || type == SCC_TOK_COMMA ||
|
||||
@@ -344,7 +344,7 @@ static scc_ast_expr_t *parse_expression_with_precedence(scc_parser_t *parser,
|
||||
// 从最底层(cast-expression)开始
|
||||
scc_ast_expr_t *left = parse_cast_expression(parser);
|
||||
if (!left)
|
||||
return null;
|
||||
return nullptr;
|
||||
|
||||
while (1) {
|
||||
const scc_lexer_tok_t *tok_ptr = scc_parser_peek(parser);
|
||||
@@ -367,11 +367,11 @@ static scc_ast_expr_t *parse_expression_with_precedence(scc_parser_t *parser,
|
||||
parse_expression_with_precedence(parser, prec + 1);
|
||||
if (!right) {
|
||||
parser_sync(parser);
|
||||
return null;
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
scc_ast_expr_t *expr = scc_malloc(sizeof(scc_ast_expr_t));
|
||||
Assert(expr != null);
|
||||
Assert(expr != nullptr);
|
||||
// FIXME pos
|
||||
scc_ast_expr_binary_init(expr, op, left, right, left->base.loc);
|
||||
left = expr;
|
||||
@@ -382,10 +382,10 @@ static scc_ast_expr_t *parse_expression_with_precedence(scc_parser_t *parser,
|
||||
scc_ast_expr_t *scc_parse_assignment_expression(scc_parser_t *parser) {
|
||||
// 先解析左侧的 unary-expression(C 标准规定赋值左边必须是
|
||||
// unary-expression)
|
||||
scc_ast_expr_t *left = null;
|
||||
scc_ast_expr_t *left = nullptr;
|
||||
left = parse_conditional_expression(parser);
|
||||
if (!left)
|
||||
return null;
|
||||
return nullptr;
|
||||
|
||||
const scc_lexer_tok_t *tok_ptr = scc_parser_peek(parser);
|
||||
if (!tok_ptr)
|
||||
@@ -406,11 +406,11 @@ scc_ast_expr_t *scc_parse_assignment_expression(scc_parser_t *parser) {
|
||||
if (!right) {
|
||||
// 错误恢复
|
||||
parser_sync(parser);
|
||||
return null;
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
scc_ast_expr_t *expr = scc_malloc(sizeof(scc_ast_expr_t));
|
||||
Assert(expr != null);
|
||||
Assert(expr != nullptr);
|
||||
scc_ast_expr_binary_init(expr, op, left, right, pos);
|
||||
left = expr;
|
||||
}
|
||||
@@ -422,7 +422,7 @@ static scc_ast_expr_t *parse_conditional_expression(scc_parser_t *parser) {
|
||||
scc_ast_expr_t *cond_expr =
|
||||
parse_expression_with_precedence(parser, PREC_LOGICAL_OR);
|
||||
if (!cond_expr)
|
||||
return null;
|
||||
return nullptr;
|
||||
|
||||
const scc_lexer_tok_t *tok_ptr = scc_parser_peek(parser);
|
||||
if (tok_ptr && tok_ptr->type == SCC_TOK_COND) {
|
||||
@@ -437,7 +437,7 @@ static scc_ast_expr_t *parse_conditional_expression(scc_parser_t *parser) {
|
||||
scc_ast_expr_t *then_expr = scc_parse_expression(parser);
|
||||
if (!then_expr) {
|
||||
parser_sync(parser);
|
||||
return null;
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
// 消耗 ':'
|
||||
@@ -445,18 +445,18 @@ static scc_ast_expr_t *parse_conditional_expression(scc_parser_t *parser) {
|
||||
SCC_ERROR(scc_parser_got_current_pos(parser),
|
||||
"Expected ':' after '?'");
|
||||
parser_sync(parser);
|
||||
return null;
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
// 解析 else 部分(右结合,再次调用 parse_conditional_expression)
|
||||
scc_ast_expr_t *else_expr = parse_conditional_expression(parser);
|
||||
if (!else_expr) {
|
||||
parser_sync(parser);
|
||||
return null;
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
scc_ast_expr_t *cond = scc_malloc(sizeof(scc_ast_expr_t));
|
||||
Assert(cond != null);
|
||||
Assert(cond != nullptr);
|
||||
scc_ast_expr_cond_init(cond, cond_expr, then_expr, else_expr, pos);
|
||||
cond_expr = cond;
|
||||
}
|
||||
@@ -466,7 +466,7 @@ static scc_ast_expr_t *parse_conditional_expression(scc_parser_t *parser) {
|
||||
// 类型转换表达式 (type-name) cast-expression
|
||||
static scc_ast_expr_t *parse_cast_expression(scc_parser_t *parser) {
|
||||
const scc_lexer_tok_t *tok_ptr = scc_parser_peek(parser);
|
||||
scc_ast_type_t *type = null;
|
||||
scc_ast_type_t *type = nullptr;
|
||||
if (tok_ptr && tok_ptr->type == SCC_TOK_L_PAREN) {
|
||||
// 尝试解析类型名
|
||||
scc_parser_store(parser);
|
||||
@@ -487,7 +487,7 @@ static scc_ast_expr_t *parse_cast_expression(scc_parser_t *parser) {
|
||||
return operand;
|
||||
}
|
||||
scc_ast_expr_t *expr = scc_malloc(sizeof(scc_ast_expr_t));
|
||||
Assert(expr != null);
|
||||
Assert(expr != nullptr);
|
||||
// FIXME pos
|
||||
scc_ast_expr_cast_init(expr, type, operand, type->base.loc);
|
||||
return expr;
|
||||
@@ -523,7 +523,7 @@ static scc_ast_expr_t *parse_unary_expression(scc_parser_t *parser) {
|
||||
*/
|
||||
const scc_lexer_tok_t *tok_ptr = scc_parser_peek(parser);
|
||||
if (!tok_ptr)
|
||||
return null;
|
||||
return nullptr;
|
||||
|
||||
scc_lexer_tok_t tok = {0};
|
||||
|
||||
@@ -539,14 +539,14 @@ static scc_ast_expr_t *parse_unary_expression(scc_parser_t *parser) {
|
||||
case SCC_TOK_NOT: // !x
|
||||
{
|
||||
if (!scc_parser_next_consume(parser, &tok))
|
||||
return null;
|
||||
return nullptr;
|
||||
scc_ast_expr_op_t op = map_token_to_unary_op(tok.type, true);
|
||||
scc_pos_t pos = tok.loc;
|
||||
scc_lexer_tok_drop(&tok);
|
||||
|
||||
// 一元运算符右结合,递归调用 parse_unary_expression
|
||||
|
||||
scc_ast_expr_t *operand = null;
|
||||
scc_ast_expr_t *operand = nullptr;
|
||||
if (tok_ptr->type == SCC_TOK_ADD_ADD ||
|
||||
tok_ptr->type == SCC_TOK_SUB_SUB) {
|
||||
operand = parse_unary_expression(parser);
|
||||
@@ -555,11 +555,11 @@ static scc_ast_expr_t *parse_unary_expression(scc_parser_t *parser) {
|
||||
}
|
||||
if (!operand) {
|
||||
parser_sync(parser);
|
||||
return null;
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
scc_ast_expr_t *expr = scc_malloc(sizeof(scc_ast_expr_t));
|
||||
Assert(expr != null);
|
||||
Assert(expr != nullptr);
|
||||
scc_ast_expr_unary_init(expr, op, operand, pos);
|
||||
return expr;
|
||||
}
|
||||
@@ -575,7 +575,7 @@ static scc_ast_expr_t *parse_sizeof_expression(scc_parser_t *parser) {
|
||||
scc_lexer_tok_t tok_ptr;
|
||||
if (!scc_parser_next_consume(parser, &tok_ptr) ||
|
||||
tok_ptr.type != SCC_TOK_SIZEOF) {
|
||||
return null;
|
||||
return nullptr;
|
||||
}
|
||||
scc_pos_t pos = tok_ptr.loc;
|
||||
scc_lexer_tok_drop(&tok_ptr);
|
||||
@@ -584,7 +584,7 @@ static scc_ast_expr_t *parse_sizeof_expression(scc_parser_t *parser) {
|
||||
if (!next) {
|
||||
SCC_ERROR(scc_parser_got_current_pos(parser),
|
||||
"Unexpected end after sizeof");
|
||||
return null;
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
scc_ast_expr_t *expr = scc_malloc(sizeof(scc_ast_expr_t));
|
||||
@@ -593,7 +593,7 @@ static scc_ast_expr_t *parse_sizeof_expression(scc_parser_t *parser) {
|
||||
scc_parser_store(parser);
|
||||
scc_parser_next(parser);
|
||||
scc_ast_type_t *type_name = scc_parse_type_name(parser);
|
||||
if (type_name == null) {
|
||||
if (type_name == nullptr) {
|
||||
scc_parser_restore(parser);
|
||||
goto next;
|
||||
}
|
||||
@@ -603,15 +603,15 @@ static scc_ast_expr_t *parse_sizeof_expression(scc_parser_t *parser) {
|
||||
"expected ')' after type-name in sizeof expression");
|
||||
}
|
||||
|
||||
Assert(type_name != null);
|
||||
scc_ast_expr_sizeof_init(expr, type_name, null, pos);
|
||||
Assert(type_name != nullptr);
|
||||
scc_ast_expr_sizeof_init(expr, type_name, nullptr, pos);
|
||||
return expr;
|
||||
}
|
||||
next:
|
||||
// 尝试解析 sizeof unary-expression
|
||||
scc_ast_expr_t *operand = parse_unary_expression(parser);
|
||||
if (operand != null) {
|
||||
scc_ast_expr_sizeof_init(expr, null, operand, pos);
|
||||
if (operand != nullptr) {
|
||||
scc_ast_expr_sizeof_init(expr, nullptr, operand, pos);
|
||||
return expr;
|
||||
}
|
||||
|
||||
@@ -622,12 +622,12 @@ next:
|
||||
// 后缀表达式
|
||||
static scc_ast_expr_t *parse_postfix_expression(scc_parser_t *parser) {
|
||||
scc_ast_expr_t *left = parse_primary_expression(parser);
|
||||
const scc_lexer_tok_t *tok_ptr = null;
|
||||
const scc_lexer_tok_t *tok_ptr = nullptr;
|
||||
scc_pos_t pos = scc_pos_create();
|
||||
if (!left) {
|
||||
tok_ptr = scc_parser_peek(parser);
|
||||
if (!(tok_ptr && tok_ptr->type == SCC_TOK_L_PAREN)) {
|
||||
return null;
|
||||
return nullptr;
|
||||
}
|
||||
pos = tok_ptr->loc;
|
||||
|
||||
@@ -636,7 +636,7 @@ static scc_ast_expr_t *parse_postfix_expression(scc_parser_t *parser) {
|
||||
scc_ast_type_t *type = scc_parse_type_name(parser);
|
||||
if (!type) {
|
||||
scc_parser_restore(parser);
|
||||
return null;
|
||||
return nullptr;
|
||||
}
|
||||
scc_parser_commit(parser);
|
||||
if (!scc_parser_consume_if(parser, SCC_TOK_R_PAREN)) {
|
||||
@@ -656,30 +656,30 @@ static scc_ast_expr_t *parse_postfix_expression(scc_parser_t *parser) {
|
||||
switch (tok_ptr->type) {
|
||||
case SCC_TOK_L_BRACKET: // left[expr]
|
||||
{
|
||||
if (!scc_parser_next_consume(parser, null))
|
||||
if (!scc_parser_next_consume(parser, nullptr))
|
||||
return left;
|
||||
pos = left->base.loc;
|
||||
|
||||
scc_ast_expr_t *index = scc_parse_expression(parser);
|
||||
if (!index) {
|
||||
parser_sync(parser);
|
||||
return null;
|
||||
return nullptr;
|
||||
}
|
||||
if (!scc_parser_consume_if(parser, SCC_TOK_R_BRACKET)) {
|
||||
SCC_ERROR(scc_parser_got_current_pos(parser),
|
||||
"Expected ']' after subscript");
|
||||
parser_sync(parser);
|
||||
return null;
|
||||
return nullptr;
|
||||
}
|
||||
scc_ast_expr_t *subscript = scc_malloc(sizeof(scc_ast_expr_t));
|
||||
Assert(subscript != null);
|
||||
Assert(subscript != nullptr);
|
||||
scc_ast_expr_array_subscript_init(subscript, left, index, pos);
|
||||
left = subscript;
|
||||
break;
|
||||
}
|
||||
case SCC_TOK_L_PAREN: // left(args)
|
||||
{
|
||||
if (!scc_parser_next_consume(parser, null))
|
||||
if (!scc_parser_next_consume(parser, nullptr))
|
||||
return left;
|
||||
pos = left->base.loc;
|
||||
scc_ast_expr_vec_t args;
|
||||
@@ -705,11 +705,11 @@ static scc_ast_expr_t *parse_postfix_expression(scc_parser_t *parser) {
|
||||
// 释放已解析的参数
|
||||
// TODO: 释放 args 中的表达式
|
||||
parser_sync(parser);
|
||||
return null;
|
||||
return nullptr;
|
||||
}
|
||||
}
|
||||
scc_ast_expr_t *call = scc_malloc(sizeof(scc_ast_expr_t));
|
||||
Assert(call != null);
|
||||
Assert(call != nullptr);
|
||||
scc_ast_expr_call_init(call, left, &args, pos);
|
||||
left = call;
|
||||
break;
|
||||
@@ -726,12 +726,12 @@ static scc_ast_expr_t *parse_postfix_expression(scc_parser_t *parser) {
|
||||
"Expected identifier after member access");
|
||||
scc_lexer_tok_drop(&op_tok);
|
||||
parser_sync(parser);
|
||||
return null;
|
||||
return nullptr;
|
||||
}
|
||||
const char *name = scc_str_as_cstr(&ident_tok.lexeme);
|
||||
|
||||
scc_ast_expr_t *member = scc_malloc(sizeof(scc_ast_expr_t));
|
||||
Assert(member != null);
|
||||
Assert(member != nullptr);
|
||||
if (op_tok.type == SCC_TOK_DOT) {
|
||||
scc_ast_expr_member_init(member, left, name, ident_tok.loc);
|
||||
} else {
|
||||
@@ -750,7 +750,7 @@ static scc_ast_expr_t *parse_postfix_expression(scc_parser_t *parser) {
|
||||
return left;
|
||||
scc_ast_expr_op_t op = map_token_to_unary_op(op_tok.type, false);
|
||||
scc_ast_expr_t *expr = scc_malloc(sizeof(scc_ast_expr_t));
|
||||
Assert(expr != null);
|
||||
Assert(expr != nullptr);
|
||||
scc_ast_expr_unary_init(expr, op, left, op_tok.loc);
|
||||
scc_lexer_tok_drop(&op_tok);
|
||||
left = expr;
|
||||
@@ -776,43 +776,43 @@ static scc_ast_expr_t *parse_primary_expression(scc_parser_t *parser) {
|
||||
*/
|
||||
const scc_lexer_tok_t *tok_ptr = scc_parser_peek(parser);
|
||||
if (!tok_ptr)
|
||||
return null;
|
||||
return nullptr;
|
||||
|
||||
scc_lexer_tok_t tok = {0};
|
||||
scc_ast_expr_t *expr = null;
|
||||
scc_ast_expr_t *expr = nullptr;
|
||||
switch (tok_ptr->type) {
|
||||
case SCC_TOK_IDENT: {
|
||||
if (!scc_parser_next_consume(parser, &tok))
|
||||
return null;
|
||||
return nullptr;
|
||||
expr = scc_malloc(sizeof(scc_ast_expr_t));
|
||||
Assert(expr != null);
|
||||
Assert(expr != nullptr);
|
||||
scc_ast_expr_identifier_init(expr, scc_str_as_cstr(&tok.lexeme),
|
||||
tok.loc);
|
||||
break;
|
||||
}
|
||||
case SCC_TOK_INT_LITERAL: {
|
||||
if (!scc_parser_next_consume(parser, &tok))
|
||||
return null;
|
||||
return nullptr;
|
||||
expr = scc_malloc(sizeof(scc_ast_expr_t));
|
||||
Assert(expr != null);
|
||||
Assert(expr != nullptr);
|
||||
scc_ast_expr_literal_int_init(expr, scc_str_as_cstr(&tok.lexeme), false,
|
||||
tok.loc);
|
||||
break;
|
||||
}
|
||||
case SCC_TOK_FLOAT_LITERAL: {
|
||||
if (!scc_parser_next_consume(parser, &tok))
|
||||
return null;
|
||||
return nullptr;
|
||||
expr = scc_malloc(sizeof(scc_ast_expr_t));
|
||||
Assert(expr != null);
|
||||
Assert(expr != nullptr);
|
||||
scc_ast_expr_literal_float_init(expr, scc_str_as_cstr(&tok.lexeme),
|
||||
false, tok.loc);
|
||||
break;
|
||||
}
|
||||
case SCC_TOK_CHAR_LITERAL: {
|
||||
if (!scc_parser_next_consume(parser, &tok))
|
||||
return null;
|
||||
return nullptr;
|
||||
expr = scc_malloc(sizeof(scc_ast_expr_t));
|
||||
Assert(expr != null);
|
||||
Assert(expr != nullptr);
|
||||
scc_ast_expr_literal_char_init(expr, scc_str_as_cstr(&tok.lexeme),
|
||||
false, tok.loc);
|
||||
break;
|
||||
@@ -822,7 +822,7 @@ static scc_ast_expr_t *parse_primary_expression(scc_parser_t *parser) {
|
||||
scc_lexer_tok_t tok;
|
||||
while (1) {
|
||||
tok_ptr = scc_parser_peek(parser);
|
||||
if (tok_ptr == null) {
|
||||
if (tok_ptr == nullptr) {
|
||||
break;
|
||||
}
|
||||
if (tok_ptr->type != SCC_TOK_STRING_LITERAL) {
|
||||
@@ -835,14 +835,14 @@ static scc_ast_expr_t *parse_primary_expression(scc_parser_t *parser) {
|
||||
}
|
||||
|
||||
expr = scc_malloc(sizeof(scc_ast_expr_t));
|
||||
Assert(expr != null);
|
||||
Assert(expr != nullptr);
|
||||
// FIXME loc
|
||||
scc_ast_expr_literal_string_init(expr, scc_str_as_cstr(&string), true,
|
||||
tok.loc);
|
||||
break;
|
||||
}
|
||||
case SCC_TOK_L_PAREN:
|
||||
scc_parser_next_consume(parser, null);
|
||||
scc_parser_next_consume(parser, nullptr);
|
||||
expr = scc_parse_expression(parser);
|
||||
if (!scc_parser_consume_if(parser, SCC_TOK_R_PAREN)) {
|
||||
SCC_ERROR(scc_parser_got_current_pos(parser),
|
||||
@@ -853,8 +853,8 @@ static scc_ast_expr_t *parse_primary_expression(scc_parser_t *parser) {
|
||||
break;
|
||||
}
|
||||
|
||||
if (expr == null) {
|
||||
return null;
|
||||
if (expr == nullptr) {
|
||||
return nullptr;
|
||||
}
|
||||
scc_parse_expr_sema(parser, expr);
|
||||
return expr;
|
||||
@@ -863,24 +863,24 @@ 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 *left = scc_parse_assignment_expression(parser);
|
||||
if (!left)
|
||||
return null;
|
||||
return nullptr;
|
||||
|
||||
const scc_lexer_tok_t *tok_ptr = null;
|
||||
const scc_lexer_tok_t *tok_ptr = nullptr;
|
||||
while (1) {
|
||||
tok_ptr = scc_parser_peek(parser);
|
||||
if (tok_ptr == null || tok_ptr->type != SCC_TOK_COMMA) {
|
||||
if (tok_ptr == nullptr || tok_ptr->type != SCC_TOK_COMMA) {
|
||||
break;
|
||||
}
|
||||
scc_pos_t pos = tok_ptr->loc;
|
||||
scc_parser_next_consume(parser, null);
|
||||
scc_parser_next_consume(parser, nullptr);
|
||||
|
||||
scc_ast_expr_t *right = scc_parse_assignment_expression(parser);
|
||||
if (!right) {
|
||||
parser_sync(parser);
|
||||
return null;
|
||||
return nullptr;
|
||||
}
|
||||
scc_ast_expr_t *expr = scc_malloc(sizeof(scc_ast_expr_t));
|
||||
Assert(expr != null);
|
||||
Assert(expr != nullptr);
|
||||
scc_ast_expr_binary_init(expr, SCC_AST_OP_COMMA, left, right, pos);
|
||||
left = expr;
|
||||
}
|
||||
|
||||
@@ -52,7 +52,7 @@ A.2.3 Statements
|
||||
|
||||
static inline scc_ast_stmt_t *ast_stmt_alloc() {
|
||||
scc_ast_stmt_t *stmt = (scc_ast_stmt_t *)scc_malloc(sizeof(scc_ast_stmt_t));
|
||||
if (stmt == null) {
|
||||
if (stmt == nullptr) {
|
||||
LOG_FATAL("Out of memory");
|
||||
}
|
||||
return stmt;
|
||||
@@ -77,7 +77,7 @@ static scc_ast_stmt_t *parse_label_statement(scc_parser_t *parser,
|
||||
scc_pos_t pos) {
|
||||
scc_lexer_tok_t tok = {0};
|
||||
if (!scc_parser_next_consume(parser, &tok)) {
|
||||
return null;
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
if (!scc_parser_consume_if(parser, SCC_TOK_COLON)) {
|
||||
@@ -86,12 +86,12 @@ static scc_ast_stmt_t *parse_label_statement(scc_parser_t *parser,
|
||||
}
|
||||
|
||||
scc_ast_stmt_t *statement = scc_parse_statement(parser);
|
||||
if (statement == null) {
|
||||
if (statement == nullptr) {
|
||||
Panic("expect stmt");
|
||||
}
|
||||
|
||||
scc_ast_stmt_t *stmt = ast_stmt_alloc();
|
||||
Assert(stmt != null);
|
||||
Assert(stmt != nullptr);
|
||||
scc_ast_stmt_label_init(stmt, scc_str_as_cstr(&tok.lexeme), statement, pos);
|
||||
return stmt;
|
||||
}
|
||||
@@ -99,25 +99,25 @@ static scc_ast_stmt_t *parse_label_statement(scc_parser_t *parser,
|
||||
static scc_ast_stmt_t *parse_case_statement(scc_parser_t *parser,
|
||||
scc_pos_t pos) {
|
||||
if (!scc_parser_consume_if(parser, SCC_TOK_CASE)) {
|
||||
return null;
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
scc_ast_expr_t *expr = null;
|
||||
scc_ast_expr_t *expr = nullptr;
|
||||
expr = scc_parser_constant_expression(parser);
|
||||
if (expr == null) {
|
||||
if (expr == nullptr) {
|
||||
SCC_ERROR(scc_parser_got_current_pos(parser),
|
||||
"Expected constant expression after case.");
|
||||
return null;
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
if (!scc_parser_consume_if(parser, SCC_TOK_COLON)) {
|
||||
SCC_ERROR(scc_parser_got_current_pos(parser),
|
||||
"Expected `:` after case.");
|
||||
return null;
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
scc_ast_stmt_t *statement = scc_parse_statement(parser);
|
||||
if (statement == null) {
|
||||
if (statement == nullptr) {
|
||||
Panic("expect stmt");
|
||||
}
|
||||
|
||||
@@ -129,17 +129,17 @@ static scc_ast_stmt_t *parse_case_statement(scc_parser_t *parser,
|
||||
static scc_ast_stmt_t *parse_default_statement(scc_parser_t *parser,
|
||||
scc_pos_t pos) {
|
||||
if (!scc_parser_consume_if(parser, SCC_TOK_DEFAULT)) {
|
||||
return null;
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
if (!scc_parser_consume_if(parser, SCC_TOK_COLON)) {
|
||||
SCC_ERROR(scc_parser_got_current_pos(parser),
|
||||
"Expected constant expression after case.");
|
||||
return null;
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
scc_ast_stmt_t *statement = scc_parse_statement(parser);
|
||||
if (statement == null) {
|
||||
if (statement == nullptr) {
|
||||
Panic("expect stmt");
|
||||
}
|
||||
|
||||
@@ -151,31 +151,31 @@ static scc_ast_stmt_t *parse_default_statement(scc_parser_t *parser,
|
||||
static scc_ast_stmt_t *parse_compound_statement(scc_parser_t *parser,
|
||||
scc_pos_t pos) {
|
||||
if (!scc_parser_consume_if(parser, SCC_TOK_L_BRACE)) {
|
||||
return null;
|
||||
return nullptr;
|
||||
}
|
||||
scc_ast_block_item_vec_t block_items;
|
||||
scc_vec_init(block_items);
|
||||
|
||||
parser->sema_callbacks.on_stmt(parser->sema_callbacks.context,
|
||||
scc_ast_stmt_t_BEGIN, null);
|
||||
scc_ast_stmt_t_BEGIN, nullptr);
|
||||
while (!scc_parser_consume_if(parser, SCC_TOK_R_BRACE)) {
|
||||
/// TODO
|
||||
// scc_parse_is_decl();
|
||||
scc_ast_node_t *ret = null;
|
||||
scc_ast_node_t *ret = nullptr;
|
||||
ret = (scc_ast_node_t *)scc_parse_declaration(parser);
|
||||
if (ret == null) {
|
||||
if (ret == nullptr) {
|
||||
ret = (scc_ast_node_t *)scc_parse_statement(parser);
|
||||
}
|
||||
if (ret == null) {
|
||||
if (ret == nullptr) {
|
||||
SCC_ERROR(scc_parser_got_current_pos(parser), "Invalid statement");
|
||||
// TODO free
|
||||
parser->errcode = 1;
|
||||
return null;
|
||||
return nullptr;
|
||||
}
|
||||
scc_vec_push(block_items, ret);
|
||||
}
|
||||
parser->sema_callbacks.on_stmt(parser->sema_callbacks.context,
|
||||
scc_ast_stmt_t_END, null);
|
||||
scc_ast_stmt_t_END, nullptr);
|
||||
|
||||
scc_ast_stmt_t *stmt = ast_stmt_alloc();
|
||||
scc_ast_stmt_compound_init(stmt, &block_items, pos);
|
||||
@@ -184,17 +184,17 @@ 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) {
|
||||
if (!scc_parser_consume_if(parser, SCC_TOK_IF)) {
|
||||
return null;
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
scc_ast_expr_t *expression = ast_parse_paren_expression(parser);
|
||||
scc_ast_stmt_t *statement = scc_parse_statement(parser);
|
||||
scc_ast_stmt_t *opt_else = null;
|
||||
scc_ast_stmt_t *opt_else = nullptr;
|
||||
|
||||
if (scc_parser_consume_if(parser, SCC_TOK_ELSE)) {
|
||||
opt_else = scc_parse_statement(parser);
|
||||
} else {
|
||||
opt_else = null;
|
||||
opt_else = nullptr;
|
||||
}
|
||||
|
||||
scc_ast_stmt_t *stmt = ast_stmt_alloc();
|
||||
@@ -205,7 +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,
|
||||
scc_pos_t pos) {
|
||||
if (!scc_parser_consume_if(parser, SCC_TOK_SWITCH)) {
|
||||
return null;
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
scc_ast_expr_t *expression = ast_parse_paren_expression(parser);
|
||||
@@ -219,7 +219,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,
|
||||
scc_pos_t pos) {
|
||||
if (!scc_parser_consume_if(parser, SCC_TOK_WHILE)) {
|
||||
return null;
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
scc_ast_expr_t *expression = ast_parse_paren_expression(parser);
|
||||
@@ -233,7 +233,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,
|
||||
scc_pos_t pos) {
|
||||
if (!scc_parser_consume_if(parser, SCC_TOK_DO)) {
|
||||
return null;
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
scc_ast_stmt_t *statement = scc_parse_statement(parser);
|
||||
@@ -243,7 +243,7 @@ static scc_ast_stmt_t *parse_do_while_statement(scc_parser_t *parser,
|
||||
"Expected 'while' after do.");
|
||||
// TODO 使用更好的错误处理,未来应当采用更好的内存管理器
|
||||
scc_free(statement);
|
||||
return null;
|
||||
return nullptr;
|
||||
}
|
||||
scc_ast_expr_t *expression = ast_parse_paren_expression(parser);
|
||||
|
||||
@@ -255,7 +255,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,
|
||||
scc_pos_t pos) {
|
||||
if (!scc_parser_consume_if(parser, SCC_TOK_FOR)) {
|
||||
return null;
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
/*
|
||||
@@ -268,14 +268,14 @@ static scc_ast_stmt_t *parse_for_statement(scc_parser_t *parser,
|
||||
"Expected '(' before like `( expression )` .");
|
||||
}
|
||||
|
||||
scc_ast_node_t *init = null;
|
||||
scc_ast_expr_t *cond = null;
|
||||
scc_ast_expr_t *incr = null;
|
||||
scc_ast_stmt_t *body = null;
|
||||
scc_ast_node_t *init = nullptr;
|
||||
scc_ast_expr_t *cond = nullptr;
|
||||
scc_ast_expr_t *incr = nullptr;
|
||||
scc_ast_stmt_t *body = nullptr;
|
||||
|
||||
// TODO use decl or expr
|
||||
init = (scc_ast_node_t *)scc_parse_declaration(parser);
|
||||
if (init == null) {
|
||||
if (init == nullptr) {
|
||||
init = (scc_ast_node_t *)scc_parse_expression(parser);
|
||||
if (!scc_parser_consume_if(parser, SCC_TOK_SEMICOLON)) {
|
||||
SCC_ERROR(scc_parser_got_current_pos(parser),
|
||||
@@ -338,13 +338,13 @@ static scc_ast_stmt_t *parse_expression_statement(scc_parser_t *parser,
|
||||
|
||||
if (scc_parser_consume_if(parser, SCC_TOK_SEMICOLON)) {
|
||||
scc_ast_stmt_t *stmt = ast_stmt_alloc();
|
||||
scc_ast_stmt_expr_init(stmt, null, pos);
|
||||
scc_ast_stmt_expr_init(stmt, nullptr, pos);
|
||||
return stmt;
|
||||
}
|
||||
|
||||
scc_ast_expr_t *expr = scc_parse_expression(parser);
|
||||
if (expr == null) {
|
||||
return null;
|
||||
if (expr == nullptr) {
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
scc_ast_stmt_t *stmt = ast_stmt_alloc();
|
||||
@@ -362,7 +362,7 @@ scc_ast_stmt_t *scc_parse_statement(scc_parser_t *parser) {
|
||||
const scc_lexer_tok_t *tok_ref;
|
||||
tok_ref = scc_parser_peek(parser);
|
||||
if (!tok_ref) {
|
||||
return null;
|
||||
return nullptr;
|
||||
}
|
||||
scc_pos_t pos = tok_ref->loc;
|
||||
switch (tok_ref->type) {
|
||||
@@ -376,7 +376,7 @@ scc_ast_stmt_t *scc_parse_statement(scc_parser_t *parser) {
|
||||
case SCC_TOK_IDENT:
|
||||
scc_parser_next(parser);
|
||||
tok_ref = scc_parser_next(parser);
|
||||
if (tok_ref == null || tok_ref->type != SCC_TOK_COLON) {
|
||||
if (tok_ref == nullptr || tok_ref->type != SCC_TOK_COLON) {
|
||||
scc_parser_reset(parser);
|
||||
break;
|
||||
}
|
||||
|
||||
@@ -177,7 +177,7 @@ parse_direct_abstract_declarator(scc_parser_t *parser, scc_ast_type_t *base,
|
||||
static inline scc_ast_type_t *ast_type_alloc() {
|
||||
scc_ast_type_t *ast_type = scc_malloc(sizeof(scc_ast_type_t));
|
||||
ast_type->base.type = SCC_AST_UNKNOWN;
|
||||
if (ast_type == null) {
|
||||
if (ast_type == nullptr) {
|
||||
LOG_FATAL("Out of memory");
|
||||
}
|
||||
return ast_type;
|
||||
@@ -194,7 +194,7 @@ static inline scc_ast_type_t *ast_type_alloc() {
|
||||
*/
|
||||
cbool scc_parse_is_decl_specifier_start(scc_parser_t *parser) {
|
||||
const scc_lexer_tok_t *tok_ptr = scc_parser_peek(parser);
|
||||
if (tok_ptr == null) {
|
||||
if (tok_ptr == nullptr) {
|
||||
return false;
|
||||
}
|
||||
switch (tok_ptr->type) {
|
||||
@@ -230,7 +230,7 @@ cbool scc_parse_is_decl_specifier_start(scc_parser_t *parser) {
|
||||
// typedef 名称(标识符也可能是类型说明符)
|
||||
case SCC_TOK_IDENT:
|
||||
return scc_parse_got_type(parser, scc_str_as_cstr(&tok_ptr->lexeme)) !=
|
||||
null;
|
||||
nullptr;
|
||||
default:
|
||||
return false;
|
||||
}
|
||||
@@ -238,7 +238,7 @@ cbool scc_parse_is_decl_specifier_start(scc_parser_t *parser) {
|
||||
|
||||
cbool scc_parse_is_type_specifier_start(scc_parser_t *parser) {
|
||||
const scc_lexer_tok_t *tok_ptr = scc_parser_peek(parser);
|
||||
if (tok_ptr == null) {
|
||||
if (tok_ptr == nullptr) {
|
||||
return false;
|
||||
}
|
||||
switch (tok_ptr->type) {
|
||||
@@ -261,7 +261,7 @@ cbool scc_parse_is_type_specifier_start(scc_parser_t *parser) {
|
||||
case SCC_TOK_IDENT:
|
||||
// 需要检查标识符是否在符号表中定义为 typedef
|
||||
return scc_parse_got_type(parser, scc_str_as_cstr(&tok_ptr->lexeme)) !=
|
||||
null;
|
||||
nullptr;
|
||||
default:
|
||||
return false;
|
||||
}
|
||||
@@ -269,7 +269,7 @@ cbool scc_parse_is_type_specifier_start(scc_parser_t *parser) {
|
||||
|
||||
cbool scc_parse_is_type_qualifier_start(scc_parser_t *parser) {
|
||||
const scc_lexer_tok_t *tok_ptr = scc_parser_peek(parser);
|
||||
if (tok_ptr == null) {
|
||||
if (tok_ptr == nullptr) {
|
||||
return false;
|
||||
}
|
||||
switch (tok_ptr->type) {
|
||||
@@ -285,7 +285,7 @@ cbool scc_parse_is_type_qualifier_start(scc_parser_t *parser) {
|
||||
|
||||
cbool scc_parse_is_storage_class_start(scc_parser_t *parser) {
|
||||
const scc_lexer_tok_t *tok_ptr = scc_parser_peek(parser);
|
||||
if (tok_ptr == null) {
|
||||
if (tok_ptr == nullptr) {
|
||||
return false;
|
||||
}
|
||||
switch (tok_ptr->type) {
|
||||
@@ -320,10 +320,10 @@ parse_type_qualifier_list(scc_parser_t *parser,
|
||||
type-qualifier
|
||||
type-qualifier-list type-qualifier
|
||||
*/
|
||||
const scc_lexer_tok_t *tok_ptr = null;
|
||||
const scc_lexer_tok_t *tok_ptr = nullptr;
|
||||
CONTINUE:
|
||||
tok_ptr = scc_parser_peek(parser);
|
||||
if (tok_ptr == null) {
|
||||
if (tok_ptr == nullptr) {
|
||||
return quals;
|
||||
}
|
||||
switch (tok_ptr->type) {
|
||||
@@ -340,7 +340,7 @@ CONTINUE:
|
||||
default:
|
||||
return quals;
|
||||
}
|
||||
scc_parser_next_consume(parser, null);
|
||||
scc_parser_next_consume(parser, nullptr);
|
||||
goto CONTINUE;
|
||||
duplicate_error:
|
||||
SCC_ERROR(scc_parser_got_current_pos(parser), "Duplicate type specifier");
|
||||
@@ -350,10 +350,10 @@ duplicate_error:
|
||||
static scc_ast_decl_specifier_t
|
||||
parse_declaration_specifiers_list(scc_parser_t *parser,
|
||||
scc_ast_decl_specifier_t quals) {
|
||||
const scc_lexer_tok_t *tok_ptr = null;
|
||||
const scc_lexer_tok_t *tok_ptr = nullptr;
|
||||
CONTINUE:
|
||||
tok_ptr = scc_parser_peek(parser);
|
||||
if (tok_ptr == null) {
|
||||
if (tok_ptr == nullptr) {
|
||||
return quals;
|
||||
}
|
||||
switch (tok_ptr->type) {
|
||||
@@ -385,7 +385,7 @@ CONTINUE:
|
||||
default:
|
||||
return quals;
|
||||
}
|
||||
scc_parser_next_consume(parser, null);
|
||||
scc_parser_next_consume(parser, nullptr);
|
||||
goto CONTINUE;
|
||||
duplicate_error:
|
||||
SCC_ERROR(scc_parser_got_current_pos(parser), "Duplicate type specifier");
|
||||
@@ -459,7 +459,7 @@ static cbool check_type_combinations(scc_parser_t *parser,
|
||||
return false;
|
||||
}
|
||||
// 如果用户定义了类型(struct/typedef),不能与任何其他类型说明符混合
|
||||
if (info->user_type != null && basic_count > 0) {
|
||||
if (info->user_type != nullptr && basic_count > 0) {
|
||||
SCC_ERROR(
|
||||
scc_parser_got_current_pos(parser),
|
||||
"Cannot combine user-defined type with basic type specifiers");
|
||||
@@ -574,12 +574,12 @@ static scc_ast_type_t *parse_record_type(scc_parser_t *parser,
|
||||
scc_lexer_tok_drop(&tok);
|
||||
|
||||
const scc_lexer_tok_t *tok_ptr = scc_parser_peek(parser);
|
||||
if (tok_ptr == null) {
|
||||
if (tok_ptr == nullptr) {
|
||||
SCC_ERROR(scc_parser_got_current_pos(parser), "Unexpected EOF");
|
||||
return null;
|
||||
return nullptr;
|
||||
}
|
||||
const char *name = null;
|
||||
scc_ast_decl_t *decl = null;
|
||||
const char *name = nullptr;
|
||||
scc_ast_decl_t *decl = nullptr;
|
||||
scc_ast_decl_vec_t member;
|
||||
scc_vec_init(member);
|
||||
|
||||
@@ -590,19 +590,19 @@ static scc_ast_type_t *parse_record_type(scc_parser_t *parser,
|
||||
}
|
||||
|
||||
if (tok_ptr && tok_ptr->type == SCC_TOK_L_BRACE) {
|
||||
scc_parser_next_consume(parser, null);
|
||||
scc_parser_next_consume(parser, nullptr);
|
||||
while (1) {
|
||||
tok_ptr = scc_parser_peek(parser);
|
||||
if (tok_ptr == null) {
|
||||
if (tok_ptr == nullptr) {
|
||||
SCC_ERROR(scc_parser_got_current_pos(parser),
|
||||
"Unexpected EOF in enum specifier");
|
||||
break;
|
||||
}
|
||||
|
||||
scc_ast_type_t *type = scc_parse_declaration_specifiers(parser);
|
||||
if (type != null) {
|
||||
if (type != nullptr) {
|
||||
decl = scc_parse_declarator(parser, type);
|
||||
if (decl != null) {
|
||||
if (decl != nullptr) {
|
||||
scc_vec_push(member, decl);
|
||||
continue;
|
||||
}
|
||||
@@ -610,20 +610,20 @@ static scc_ast_type_t *parse_record_type(scc_parser_t *parser,
|
||||
|
||||
if (tok_ptr->type == SCC_TOK_SEMICOLON) {
|
||||
// FIXME check semicolon
|
||||
scc_parser_next_consume(parser, null);
|
||||
scc_parser_next_consume(parser, nullptr);
|
||||
} else if (tok_ptr->type == SCC_TOK_R_BRACE) {
|
||||
scc_parser_next_consume(parser, null);
|
||||
scc_parser_next_consume(parser, nullptr);
|
||||
break;
|
||||
} else {
|
||||
SCC_ERROR(scc_parser_got_current_pos(parser),
|
||||
"Unexpected token in struct/union specifier");
|
||||
scc_parser_next_consume(parser, null);
|
||||
scc_parser_next_consume(parser, nullptr);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
decl = scc_malloc(sizeof(scc_ast_decl_t));
|
||||
Assert(decl != null);
|
||||
Assert(decl != nullptr);
|
||||
if (type_kind == SCC_AST_TYPE_STRUCT) {
|
||||
scc_ast_decl_struct_init(decl, name, &member, pos);
|
||||
} else {
|
||||
@@ -631,11 +631,11 @@ static scc_ast_type_t *parse_record_type(scc_parser_t *parser,
|
||||
}
|
||||
scc_parse_decl_sema(parser, decl);
|
||||
} else {
|
||||
if (name == null) {
|
||||
if (name == nullptr) {
|
||||
SCC_ERROR(scc_parser_got_current_pos(parser),
|
||||
"Expected name in struct/union specifier");
|
||||
// FIXME memory leak
|
||||
return null;
|
||||
return nullptr;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -665,18 +665,18 @@ static scc_ast_type_t *parse_enum_type(scc_parser_t *parser) {
|
||||
scc_pos_t pos = tok.loc;
|
||||
if (tok.type != SCC_TOK_ENUM) {
|
||||
SCC_ERROR(scc_parser_got_current_pos(parser), "Expected 'enum'");
|
||||
return null;
|
||||
return nullptr;
|
||||
}
|
||||
scc_lexer_tok_drop(&tok);
|
||||
|
||||
const scc_lexer_tok_t *tok_ptr = scc_parser_peek(parser);
|
||||
if (tok_ptr == null) {
|
||||
if (tok_ptr == nullptr) {
|
||||
SCC_ERROR(scc_parser_got_current_pos(parser), "Unexpected EOF");
|
||||
return null;
|
||||
return nullptr;
|
||||
}
|
||||
scc_ast_type_t *type = ast_type_alloc();
|
||||
const char *name = null;
|
||||
scc_ast_decl_t *decl = null;
|
||||
const char *name = nullptr;
|
||||
scc_ast_decl_t *decl = nullptr;
|
||||
scc_ast_decl_vec_t member;
|
||||
scc_vec_init(member);
|
||||
|
||||
@@ -687,10 +687,10 @@ static scc_ast_type_t *parse_enum_type(scc_parser_t *parser) {
|
||||
}
|
||||
|
||||
if (tok_ptr && tok_ptr->type == SCC_TOK_L_BRACE) {
|
||||
scc_parser_next_consume(parser, null);
|
||||
scc_parser_next_consume(parser, nullptr);
|
||||
while (1) {
|
||||
tok_ptr = scc_parser_peek(parser);
|
||||
if (tok_ptr == null) {
|
||||
if (tok_ptr == nullptr) {
|
||||
SCC_ERROR(scc_parser_got_current_pos(parser),
|
||||
"Unexpected EOF in enum specifier");
|
||||
break;
|
||||
@@ -703,13 +703,13 @@ static scc_ast_type_t *parse_enum_type(scc_parser_t *parser) {
|
||||
break;
|
||||
}
|
||||
|
||||
scc_ast_expr_t *enum_item_init = null;
|
||||
scc_ast_expr_t *enum_item_init = nullptr;
|
||||
if (scc_parser_consume_if(parser, SCC_TOK_ASSIGN)) {
|
||||
enum_item_init = scc_parser_constant_expression(parser);
|
||||
}
|
||||
|
||||
scc_ast_decl_t *enum_item_decl = scc_malloc(sizeof(scc_ast_decl_t));
|
||||
Assert(enum_item_decl != null);
|
||||
Assert(enum_item_decl != nullptr);
|
||||
scc_ast_decl_val_init(enum_item_decl, type,
|
||||
scc_str_as_cstr(&tok.lexeme), enum_item_init,
|
||||
tok.loc);
|
||||
@@ -719,34 +719,35 @@ static scc_ast_type_t *parse_enum_type(scc_parser_t *parser) {
|
||||
|
||||
cbool got_comma = false;
|
||||
if (tok_ptr && tok_ptr->type == SCC_TOK_COMMA) {
|
||||
scc_parser_next_consume(parser, null);
|
||||
scc_parser_next_consume(parser, nullptr);
|
||||
tok_ptr = scc_parser_peek(parser);
|
||||
got_comma = true;
|
||||
}
|
||||
if (tok_ptr && tok_ptr->type == SCC_TOK_R_BRACE) {
|
||||
scc_parser_next_consume(parser, null);
|
||||
scc_parser_next_consume(parser, nullptr);
|
||||
break;
|
||||
} else {
|
||||
if (got_comma) {
|
||||
continue;
|
||||
}
|
||||
SCC_ERROR(tok_ptr != null ? tok_ptr->loc
|
||||
: scc_parser_got_current_pos(parser),
|
||||
SCC_ERROR(tok_ptr != nullptr
|
||||
? tok_ptr->loc
|
||||
: scc_parser_got_current_pos(parser),
|
||||
"Unexpected token in enum specifier");
|
||||
scc_parser_next_consume(parser, null);
|
||||
scc_parser_next_consume(parser, nullptr);
|
||||
break;
|
||||
}
|
||||
}
|
||||
decl = scc_malloc(sizeof(scc_ast_decl_t));
|
||||
Assert(decl != null);
|
||||
Assert(decl != nullptr);
|
||||
scc_ast_decl_enum_init(decl, name, &member, pos);
|
||||
scc_parse_decl_sema(parser, decl);
|
||||
} else {
|
||||
if (name == null) {
|
||||
if (name == nullptr) {
|
||||
SCC_ERROR(scc_parser_got_current_pos(parser),
|
||||
"Expected name in enum specifier");
|
||||
// FIXME memory leak
|
||||
return null;
|
||||
return nullptr;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -757,11 +758,11 @@ static scc_ast_type_t *parse_enum_type(scc_parser_t *parser) {
|
||||
static scc_ast_type_t *parse_type_specifier(scc_parser_t *parser) {
|
||||
type_spec_info_t info = {0};
|
||||
if (!scc_parse_is_type_specifier_start(parser))
|
||||
return null;
|
||||
const scc_lexer_tok_t *tok_ptr = null;
|
||||
return nullptr;
|
||||
const scc_lexer_tok_t *tok_ptr = nullptr;
|
||||
tok_ptr = scc_parser_peek(parser);
|
||||
if (tok_ptr == null) {
|
||||
return null;
|
||||
if (tok_ptr == nullptr) {
|
||||
return nullptr;
|
||||
}
|
||||
scc_pos_t pos = tok_ptr->loc;
|
||||
|
||||
@@ -778,13 +779,13 @@ static scc_ast_type_t *parse_type_specifier(scc_parser_t *parser) {
|
||||
case SCC_TOK_IDENT:
|
||||
info.user_type =
|
||||
scc_parse_got_type(parser, scc_str_as_cstr(&tok_ptr->lexeme));
|
||||
if (info.user_type == null) {
|
||||
if (info.user_type == nullptr) {
|
||||
SCC_ERROR(scc_parser_got_current_pos(parser),
|
||||
"Expected type specifier %s",
|
||||
scc_str_as_cstr(&tok_ptr->lexeme));
|
||||
}
|
||||
scc_parser_next_consume(parser, null);
|
||||
Assert(info.user_type != null);
|
||||
scc_parser_next_consume(parser, nullptr);
|
||||
Assert(info.user_type != nullptr);
|
||||
goto done;
|
||||
default:
|
||||
break;
|
||||
@@ -792,7 +793,7 @@ static scc_ast_type_t *parse_type_specifier(scc_parser_t *parser) {
|
||||
|
||||
while (1) {
|
||||
tok_ptr = scc_parser_peek(parser);
|
||||
if (tok_ptr == null) {
|
||||
if (tok_ptr == nullptr) {
|
||||
break;
|
||||
}
|
||||
switch (tok_ptr->type) {
|
||||
@@ -800,32 +801,32 @@ static scc_ast_type_t *parse_type_specifier(scc_parser_t *parser) {
|
||||
if (info.is_void)
|
||||
goto duplicate_error;
|
||||
info.is_void = true;
|
||||
scc_parser_next_consume(parser, null);
|
||||
scc_parser_next_consume(parser, nullptr);
|
||||
break;
|
||||
case SCC_TOK_CHAR:
|
||||
if (info.is_char)
|
||||
goto duplicate_error;
|
||||
info.is_char = true;
|
||||
scc_parser_next_consume(parser, null);
|
||||
scc_parser_next_consume(parser, nullptr);
|
||||
break;
|
||||
case SCC_TOK_SHORT:
|
||||
if (info.is_short)
|
||||
goto duplicate_error;
|
||||
info.is_short = true;
|
||||
scc_parser_next_consume(parser, null);
|
||||
scc_parser_next_consume(parser, nullptr);
|
||||
break;
|
||||
case SCC_TOK_INT:
|
||||
if (info.is_int)
|
||||
goto duplicate_error;
|
||||
info.is_int = true;
|
||||
scc_parser_next_consume(parser, null);
|
||||
scc_parser_next_consume(parser, nullptr);
|
||||
break;
|
||||
case SCC_TOK_LONG:
|
||||
// long 可以出现两次
|
||||
if (info.is_long_long) {
|
||||
SCC_ERROR(scc_parser_got_current_pos(parser),
|
||||
"Three 'long's in type specifier");
|
||||
return null;
|
||||
return nullptr;
|
||||
}
|
||||
if (info.is_long) {
|
||||
info.is_long_long = true;
|
||||
@@ -833,49 +834,49 @@ static scc_ast_type_t *parse_type_specifier(scc_parser_t *parser) {
|
||||
} else {
|
||||
info.is_long = true;
|
||||
}
|
||||
scc_parser_next_consume(parser, null);
|
||||
scc_parser_next_consume(parser, nullptr);
|
||||
break;
|
||||
case SCC_TOK_FLOAT:
|
||||
if (info.is_float)
|
||||
goto duplicate_error;
|
||||
info.is_float = true;
|
||||
scc_parser_next_consume(parser, null);
|
||||
scc_parser_next_consume(parser, nullptr);
|
||||
break;
|
||||
case SCC_TOK_DOUBLE:
|
||||
if (info.is_double)
|
||||
goto duplicate_error;
|
||||
info.is_double = true;
|
||||
scc_parser_next_consume(parser, null);
|
||||
scc_parser_next_consume(parser, nullptr);
|
||||
break;
|
||||
case SCC_TOK_BOOL:
|
||||
if (info.is_bool)
|
||||
goto duplicate_error;
|
||||
info.is_bool = true;
|
||||
scc_parser_next_consume(parser, null);
|
||||
scc_parser_next_consume(parser, nullptr);
|
||||
break;
|
||||
case SCC_TOK_SIGNED:
|
||||
if (info.is_unsigned || info.is_signed) {
|
||||
SCC_ERROR(scc_parser_got_current_pos(parser),
|
||||
"Both 'signed' and 'unsigned' in type specifier");
|
||||
return null;
|
||||
return nullptr;
|
||||
}
|
||||
info.is_signed = true;
|
||||
scc_parser_next_consume(parser, null);
|
||||
scc_parser_next_consume(parser, nullptr);
|
||||
break;
|
||||
case SCC_TOK_UNSIGNED:
|
||||
if (info.is_unsigned || info.is_signed) {
|
||||
SCC_ERROR(scc_parser_got_current_pos(parser),
|
||||
"Both 'signed' and 'unsigned' in type specifier");
|
||||
return null;
|
||||
return nullptr;
|
||||
}
|
||||
info.is_unsigned = true;
|
||||
scc_parser_next_consume(parser, null);
|
||||
scc_parser_next_consume(parser, nullptr);
|
||||
break;
|
||||
case SCC_TOK_COMPLEX:
|
||||
if (info.is_complex)
|
||||
goto duplicate_error;
|
||||
info.is_complex = true;
|
||||
scc_parser_next_consume(parser, null);
|
||||
scc_parser_next_consume(parser, nullptr);
|
||||
break;
|
||||
default:
|
||||
goto done;
|
||||
@@ -883,12 +884,12 @@ static scc_ast_type_t *parse_type_specifier(scc_parser_t *parser) {
|
||||
}
|
||||
done:
|
||||
if (!check_type_combinations(parser, &info)) {
|
||||
return null;
|
||||
return nullptr;
|
||||
}
|
||||
return build_type_from_info(&info, pos);
|
||||
duplicate_error:
|
||||
SCC_ERROR(scc_parser_got_current_pos(parser), "Duplicate type specifier");
|
||||
return null;
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
static scc_ast_type_t *parse_pointer(scc_parser_t *parser,
|
||||
@@ -900,15 +901,15 @@ static scc_ast_type_t *parse_pointer(scc_parser_t *parser,
|
||||
* type-qualifier-list(opt) pointer
|
||||
*/
|
||||
const scc_lexer_tok_t *tok_ptr = scc_parser_peek(parser);
|
||||
if (tok_ptr == null || tok_ptr->type != SCC_TOK_MUL) {
|
||||
if (tok_ptr == nullptr || tok_ptr->type != SCC_TOK_MUL) {
|
||||
return pointee;
|
||||
}
|
||||
scc_pos_t pos = tok_ptr->loc;
|
||||
scc_parser_next_consume(parser, null);
|
||||
scc_parser_next_consume(parser, nullptr);
|
||||
|
||||
scc_ast_type_t *pointer = ast_type_alloc();
|
||||
if (pointee == null) {
|
||||
Assert(delay_pointee_ptr != null);
|
||||
if (pointee == nullptr) {
|
||||
Assert(delay_pointee_ptr != nullptr);
|
||||
*delay_pointee_ptr = pointer;
|
||||
pointee = pointer;
|
||||
}
|
||||
@@ -931,17 +932,17 @@ static void parse_parameter_type_list(scc_parser_t *parser,
|
||||
declaration-specifiers declarator
|
||||
declaration-specifiers abstract-declarator(opt)
|
||||
*/
|
||||
scc_ast_decl_t *param = null;
|
||||
scc_ast_decl_t *decl = null;
|
||||
const scc_lexer_tok_t *tok_ptr = null;
|
||||
scc_ast_decl_t *param = nullptr;
|
||||
scc_ast_decl_t *decl = nullptr;
|
||||
const scc_lexer_tok_t *tok_ptr = nullptr;
|
||||
while (1) {
|
||||
// FIXME
|
||||
scc_ast_type_t *type = scc_parse_declaration_specifiers(parser);
|
||||
if (type == null) {
|
||||
if (type == nullptr) {
|
||||
break;
|
||||
}
|
||||
decl = scc_parse_declarator(parser, type);
|
||||
if (decl == null) {
|
||||
if (decl == nullptr) {
|
||||
break;
|
||||
}
|
||||
|
||||
@@ -957,18 +958,18 @@ static void parse_parameter_type_list(scc_parser_t *parser,
|
||||
break;
|
||||
}
|
||||
|
||||
scc_parser_next_consume(parser, null);
|
||||
scc_parser_next_consume(parser, nullptr);
|
||||
tok_ptr = scc_parser_peek(parser);
|
||||
if (tok_ptr->type == SCC_TOK_ELLIPSIS) {
|
||||
param = scc_malloc(sizeof(scc_ast_decl_t));
|
||||
Assert(param != null);
|
||||
Assert(param != nullptr);
|
||||
// FIXME
|
||||
type = scc_malloc(sizeof(scc_ast_type_t));
|
||||
Assert(type != null);
|
||||
Assert(type != nullptr);
|
||||
scc_ast_type_builtin_init(type, SCC_AST_BUILTIN_TYPE_VA_LIST,
|
||||
tok_ptr->loc);
|
||||
scc_ast_decl_param_init(param, type, null, tok_ptr->loc);
|
||||
scc_parser_next_consume(parser, null);
|
||||
scc_ast_decl_param_init(param, type, nullptr, tok_ptr->loc);
|
||||
scc_parser_next_consume(parser, nullptr);
|
||||
scc_vec_push(*params, param);
|
||||
break;
|
||||
}
|
||||
@@ -977,7 +978,7 @@ static void parse_parameter_type_list(scc_parser_t *parser,
|
||||
|
||||
static inline cbool parse_function_parameters_start(scc_parser_t *parser) {
|
||||
const scc_lexer_tok_t *tok_ptr = scc_parser_peek(parser);
|
||||
if (tok_ptr == null) {
|
||||
if (tok_ptr == nullptr) {
|
||||
return false;
|
||||
}
|
||||
if (scc_parse_is_decl_specifier_start(parser)) {
|
||||
@@ -1003,14 +1004,14 @@ static void parse_function_parameters(scc_parser_t *parser,
|
||||
}
|
||||
|
||||
static scc_ast_expr_t *parse_array_size_type(scc_parser_t *parser) {
|
||||
const scc_lexer_tok_t *tok_ptr = null;
|
||||
const scc_lexer_tok_t *tok_ptr = nullptr;
|
||||
if (!scc_parser_consume_if(parser, SCC_TOK_L_BRACKET)) {
|
||||
SCC_ERROR(scc_parser_got_current_pos(parser), "Expect '['");
|
||||
parser->errcode = 1;
|
||||
return null;
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
scc_ast_expr_t *size = null;
|
||||
scc_ast_expr_t *size = nullptr;
|
||||
scc_ast_decl_specifier_t quals = {0};
|
||||
if (scc_parse_is_type_qualifier_start(parser)) {
|
||||
// static assignment-expression
|
||||
@@ -1019,7 +1020,7 @@ static scc_ast_expr_t *parse_array_size_type(scc_parser_t *parser) {
|
||||
// TODO
|
||||
}
|
||||
tok_ptr = scc_parser_peek(parser);
|
||||
if (tok_ptr != null && tok_ptr->type != SCC_TOK_R_BRACKET) {
|
||||
if (tok_ptr != nullptr && tok_ptr->type != SCC_TOK_R_BRACKET) {
|
||||
size = scc_parse_expression(parser);
|
||||
}
|
||||
} else if (scc_parser_consume_if(parser, SCC_TOK_MUL)) {
|
||||
@@ -1031,14 +1032,14 @@ static scc_ast_expr_t *parse_array_size_type(scc_parser_t *parser) {
|
||||
} else {
|
||||
// assignment-expression(opt)
|
||||
tok_ptr = scc_parser_peek(parser);
|
||||
if (tok_ptr != null && tok_ptr->type != SCC_TOK_R_BRACKET) {
|
||||
if (tok_ptr != nullptr && tok_ptr->type != SCC_TOK_R_BRACKET) {
|
||||
size = scc_parse_expression(parser);
|
||||
}
|
||||
}
|
||||
if (!scc_parser_consume_if(parser, SCC_TOK_R_BRACKET)) {
|
||||
SCC_ERROR(scc_parser_got_current_pos(parser), "expect ']'");
|
||||
parser->errcode = 1;
|
||||
return null;
|
||||
return nullptr;
|
||||
}
|
||||
return size;
|
||||
}
|
||||
@@ -1071,16 +1072,16 @@ static scc_ast_type_t *
|
||||
parse_direct_declarator(scc_parser_t *parser, scc_ast_type_t *base,
|
||||
scc_ast_type_t **delay_pointee_ptr,
|
||||
scc_lexer_tok_t *tok_ident) {
|
||||
const scc_lexer_tok_t *tok_ptr = null;
|
||||
scc_ast_type_t *ret = null;
|
||||
const scc_lexer_tok_t *tok_ptr = nullptr;
|
||||
scc_ast_type_t *ret = nullptr;
|
||||
// direct-abstract-declarator
|
||||
tok_ptr = scc_parser_peek(parser);
|
||||
if (tok_ptr == null) {
|
||||
if (tok_ptr == nullptr) {
|
||||
return base;
|
||||
}
|
||||
|
||||
if (tok_ptr->type == SCC_TOK_IDENT) {
|
||||
Assert(tok_ident != null);
|
||||
Assert(tok_ident != nullptr);
|
||||
if (tok_ident->type != SCC_TOK_UNKNOWN) {
|
||||
SCC_ERROR(scc_parser_got_current_pos(parser),
|
||||
"Got double identifier in declarator");
|
||||
@@ -1092,8 +1093,8 @@ parse_direct_declarator(scc_parser_t *parser, scc_ast_type_t *base,
|
||||
tok_ident);
|
||||
} else if (tok_ptr->type == SCC_TOK_L_PAREN) {
|
||||
// () SCC_TOK_L_PAREN
|
||||
scc_parser_next_consume(parser, null);
|
||||
scc_ast_type_t *delay_pointee = null;
|
||||
scc_parser_next_consume(parser, nullptr);
|
||||
scc_ast_type_t *delay_pointee = nullptr;
|
||||
if (parse_function_parameters_start(parser)) {
|
||||
scc_ast_decl_vec_t params;
|
||||
parse_function_parameters(parser, ¶ms);
|
||||
@@ -1103,10 +1104,10 @@ parse_direct_declarator(scc_parser_t *parser, scc_ast_type_t *base,
|
||||
return parse_direct_declarator(parser, ret, delay_pointee_ptr,
|
||||
tok_ident);
|
||||
} else {
|
||||
ret = parse_declarator(parser, null, &delay_pointee, tok_ident);
|
||||
if (ret == null) {
|
||||
ret = parse_declarator(parser, nullptr, &delay_pointee, tok_ident);
|
||||
if (ret == nullptr) {
|
||||
SCC_ERROR(tok_ident->loc, "parse_declarator failed");
|
||||
Panic("parse_declarator failed ret == null");
|
||||
Panic("parse_declarator failed ret == nullptr");
|
||||
}
|
||||
if (!scc_parser_consume_if(parser, SCC_TOK_R_PAREN)) {
|
||||
SCC_ERROR(scc_parser_got_current_pos(parser), "expect ')'");
|
||||
@@ -1114,7 +1115,7 @@ parse_direct_declarator(scc_parser_t *parser, scc_ast_type_t *base,
|
||||
base = parse_direct_declarator(parser, base, delay_pointee_ptr,
|
||||
tok_ident);
|
||||
Assert(SCC_AST_IS_A(scc_ast_type_t, base));
|
||||
Assert(delay_pointee != null);
|
||||
Assert(delay_pointee != nullptr);
|
||||
delay_pointee->pointer.pointee = base;
|
||||
return ret;
|
||||
}
|
||||
@@ -1158,18 +1159,18 @@ parse_abstract_declarator(scc_parser_t *parser, scc_ast_type_t *base,
|
||||
static scc_ast_type_t *
|
||||
parse_direct_abstract_declarator(scc_parser_t *parser, scc_ast_type_t *base,
|
||||
scc_ast_type_t **delay_pointee_ptr) {
|
||||
const scc_lexer_tok_t *tok_ptr = null;
|
||||
scc_ast_type_t *ret = null;
|
||||
const scc_lexer_tok_t *tok_ptr = nullptr;
|
||||
scc_ast_type_t *ret = nullptr;
|
||||
// direct-abstract-declarator
|
||||
tok_ptr = scc_parser_peek(parser);
|
||||
if (tok_ptr == null) {
|
||||
if (tok_ptr == nullptr) {
|
||||
return base;
|
||||
}
|
||||
|
||||
if (tok_ptr->type == SCC_TOK_L_PAREN) {
|
||||
// () SCC_TOK_L_PAREN
|
||||
scc_parser_next_consume(parser, null);
|
||||
scc_ast_type_t *delay_pointee = null;
|
||||
scc_parser_next_consume(parser, nullptr);
|
||||
scc_ast_type_t *delay_pointee = nullptr;
|
||||
if (parse_function_parameters_start(parser)) {
|
||||
scc_ast_decl_vec_t params;
|
||||
parse_function_parameters(parser, ¶ms);
|
||||
@@ -1179,14 +1180,14 @@ parse_direct_abstract_declarator(scc_parser_t *parser, scc_ast_type_t *base,
|
||||
return parse_direct_abstract_declarator(parser, ret,
|
||||
delay_pointee_ptr);
|
||||
} else {
|
||||
ret = parse_abstract_declarator(parser, null, &delay_pointee);
|
||||
Assert(ret != null);
|
||||
ret = parse_abstract_declarator(parser, nullptr, &delay_pointee);
|
||||
Assert(ret != nullptr);
|
||||
if (!scc_parser_consume_if(parser, SCC_TOK_R_PAREN)) {
|
||||
SCC_ERROR(scc_parser_got_current_pos(parser), "expect ')'");
|
||||
}
|
||||
base = parse_direct_abstract_declarator(parser, base,
|
||||
delay_pointee_ptr);
|
||||
Assert(delay_pointee != null);
|
||||
Assert(delay_pointee != nullptr);
|
||||
delay_pointee->pointer.pointee = base;
|
||||
}
|
||||
return ret;
|
||||
@@ -1208,20 +1209,21 @@ scc_ast_decl_t *scc_parse_declarator(scc_parser_t *parser,
|
||||
scc_ast_type_t *type) {
|
||||
scc_lexer_tok_t decl_name_tok = {0};
|
||||
scc_ast_type_t *decl_type =
|
||||
parse_declarator(parser, type, null, &decl_name_tok);
|
||||
scc_ast_decl_t *decl = null;
|
||||
parse_declarator(parser, type, nullptr, &decl_name_tok);
|
||||
scc_ast_decl_t *decl = nullptr;
|
||||
decl = scc_malloc(sizeof(scc_ast_decl_t));
|
||||
Assert(decl != null);
|
||||
Assert(decl != nullptr);
|
||||
Assert(decl_name_tok.type == SCC_TOK_IDENT ||
|
||||
decl_name_tok.type == SCC_TOK_UNKNOWN);
|
||||
|
||||
// FIXME memory leak
|
||||
const char *name = decl_name_tok.type == SCC_TOK_IDENT
|
||||
? scc_str_as_cstr(&decl_name_tok.lexeme)
|
||||
: null;
|
||||
: nullptr;
|
||||
|
||||
if (decl_type->base.type == SCC_AST_TYPE_FUNCTION) {
|
||||
scc_ast_decl_func_init(decl, decl_type, name, null, decl_name_tok.loc);
|
||||
scc_ast_decl_func_init(decl, decl_type, name, nullptr,
|
||||
decl_name_tok.loc);
|
||||
// TODO using sema to change it
|
||||
if (type->quals.is_inline) {
|
||||
decl_type->quals.is_inline = true;
|
||||
@@ -1229,7 +1231,7 @@ scc_ast_decl_t *scc_parse_declarator(scc_parser_t *parser,
|
||||
type->quals.is_inline = false;
|
||||
}
|
||||
} else {
|
||||
scc_ast_decl_unsafe_val_init(decl, decl_type, name, null,
|
||||
scc_ast_decl_unsafe_val_init(decl, decl_type, name, nullptr,
|
||||
decl_name_tok.loc);
|
||||
}
|
||||
|
||||
@@ -1237,17 +1239,17 @@ scc_ast_decl_t *scc_parse_declarator(scc_parser_t *parser,
|
||||
if (decl_type->base.type == SCC_AST_TYPE_STRUCT ||
|
||||
decl_type->base.type == SCC_AST_TYPE_UNION ||
|
||||
decl_type->base.type == SCC_AST_TYPE_ENUM) {
|
||||
if (decl_type->record.decl == null) {
|
||||
if (decl_type->record.decl == nullptr) {
|
||||
decl = scc_malloc(sizeof(scc_ast_decl_t));
|
||||
Assert(decl != null);
|
||||
Assert(decl != nullptr);
|
||||
if (decl_type->base.type == SCC_AST_TYPE_STRUCT) {
|
||||
scc_ast_decl_struct_init(decl, decl_type->record.name, null,
|
||||
decl_type->base.loc);
|
||||
scc_ast_decl_struct_init(decl, decl_type->record.name,
|
||||
nullptr, decl_type->base.loc);
|
||||
} else if (decl_type->base.type == SCC_AST_TYPE_UNION) {
|
||||
scc_ast_decl_union_init(decl, decl_type->record.name, null,
|
||||
decl_type->base.loc);
|
||||
scc_ast_decl_union_init(decl, decl_type->record.name,
|
||||
nullptr, decl_type->base.loc);
|
||||
} else {
|
||||
scc_ast_decl_enum_init(decl, type->record.name, null,
|
||||
scc_ast_decl_enum_init(decl, type->record.name, nullptr,
|
||||
decl_type->base.loc);
|
||||
}
|
||||
} else {
|
||||
@@ -1256,7 +1258,7 @@ scc_ast_decl_t *scc_parse_declarator(scc_parser_t *parser,
|
||||
}
|
||||
} else {
|
||||
decl = scc_malloc(sizeof(scc_ast_decl_t));
|
||||
scc_ast_decl_unsafe_val_init(decl, type, null, null,
|
||||
scc_ast_decl_unsafe_val_init(decl, type, nullptr, nullptr,
|
||||
decl_type->base.loc);
|
||||
}
|
||||
}
|
||||
@@ -1265,7 +1267,7 @@ scc_ast_decl_t *scc_parse_declarator(scc_parser_t *parser,
|
||||
|
||||
scc_ast_type_t *scc_parse_declaration_specifiers(scc_parser_t *parser) {
|
||||
if (!scc_parse_is_decl_specifier_start(parser)) {
|
||||
return null;
|
||||
return nullptr;
|
||||
}
|
||||
scc_ast_decl_specifier_t spec = {0};
|
||||
|
||||
@@ -1275,10 +1277,10 @@ scc_ast_type_t *scc_parse_declaration_specifiers(scc_parser_t *parser) {
|
||||
|
||||
spec = parse_declaration_specifiers_list(parser, spec);
|
||||
scc_ast_type_t *specifier = parse_type_specifier(parser);
|
||||
if (specifier == null) {
|
||||
if (specifier == nullptr) {
|
||||
SCC_ERROR(scc_parser_got_current_pos(parser),
|
||||
"declaration specifier can't have type specifier");
|
||||
return null;
|
||||
return nullptr;
|
||||
}
|
||||
specifier->quals = spec;
|
||||
|
||||
@@ -1288,16 +1290,16 @@ scc_ast_type_t *scc_parse_declaration_specifiers(scc_parser_t *parser) {
|
||||
scc_ast_type_t *scc_parse_type_name(scc_parser_t *parser) {
|
||||
if (!(scc_parse_is_type_specifier_start(parser) ||
|
||||
scc_parse_is_type_qualifier_start(parser))) {
|
||||
return null;
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
scc_ast_type_t *ret = null;
|
||||
scc_ast_type_t *ret = nullptr;
|
||||
scc_ast_decl_specifier_t spec = {0};
|
||||
spec = parse_type_qualifier_list(parser, spec);
|
||||
ret = parse_type_specifier(parser);
|
||||
if (ret != null) {
|
||||
if (ret != nullptr) {
|
||||
ret->quals = spec;
|
||||
}
|
||||
ret = parse_abstract_declarator(parser, ret, null);
|
||||
ret = parse_abstract_declarator(parser, ret, nullptr);
|
||||
return ret;
|
||||
}
|
||||
|
||||
@@ -13,7 +13,7 @@ static scc_ast_type_t *dummy_got_type_callback(void *context,
|
||||
const char *name) {
|
||||
(void)context;
|
||||
(void)name;
|
||||
return null;
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
#define ASSIGN_PTR_OR_DEFAULT(assigned_val, value, default) \
|
||||
@@ -21,10 +21,10 @@ static scc_ast_type_t *dummy_got_type_callback(void *context,
|
||||
|
||||
void scc_parser_init(scc_parser_t *parser, scc_lexer_tok_ring_t *tok_ring,
|
||||
scc_sema_callbacks_t *callbacks) {
|
||||
Assert(parser != null && tok_ring != null);
|
||||
Assert(parser != nullptr && tok_ring != nullptr);
|
||||
parser->ring = tok_ring;
|
||||
parser->errcode = 0;
|
||||
parser->translation_unit = null;
|
||||
parser->translation_unit = nullptr;
|
||||
if (callbacks) {
|
||||
ASSIGN_PTR_OR_DEFAULT(parser->sema_callbacks.on_decl,
|
||||
callbacks->on_decl, dummy_sema_callback);
|
||||
@@ -43,7 +43,7 @@ void scc_parser_init(scc_parser_t *parser, scc_lexer_tok_ring_t *tok_ring,
|
||||
parser->sema_callbacks.on_expr = dummy_sema_callback;
|
||||
parser->sema_callbacks.on_type = dummy_sema_callback;
|
||||
parser->sema_callbacks.got_type = dummy_got_type_callback;
|
||||
parser->sema_callbacks.context = null;
|
||||
parser->sema_callbacks.context = nullptr;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -55,7 +55,7 @@ scc_ast_translation_unit_t *scc_parse_translation_unit(scc_parser_t *parser) {
|
||||
scc_ast_translation_unit_t *unit =
|
||||
scc_malloc(sizeof(scc_ast_translation_unit_t));
|
||||
if (!unit)
|
||||
return null;
|
||||
return nullptr;
|
||||
unit->base.type = SCC_AST_TRANSLATION_UNIT;
|
||||
scc_vec_init(unit->declarations);
|
||||
|
||||
@@ -66,7 +66,7 @@ scc_ast_translation_unit_t *scc_parse_translation_unit(scc_parser_t *parser) {
|
||||
*/
|
||||
while (1) {
|
||||
scc_ast_decl_t *decl = scc_parse_declaration(parser);
|
||||
if (decl != null) {
|
||||
if (decl != nullptr) {
|
||||
scc_vec_push(unit->declarations, decl);
|
||||
} else {
|
||||
break;
|
||||
@@ -77,7 +77,7 @@ scc_ast_translation_unit_t *scc_parse_translation_unit(scc_parser_t *parser) {
|
||||
break;
|
||||
}
|
||||
const scc_lexer_tok_t *tok = scc_parser_peek(parser);
|
||||
if (tok == null || tok->type == SCC_TOK_EOF) {
|
||||
if (tok == nullptr || tok->type == SCC_TOK_EOF) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
@@ -87,7 +87,7 @@ scc_ast_translation_unit_t *scc_parse_translation_unit(scc_parser_t *parser) {
|
||||
SCC_ERROR(scc_parser_got_current_pos(parser), "parser error: %d",
|
||||
parser->errcode);
|
||||
scc_free(unit);
|
||||
return null;
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
Assert(unit->base.type == SCC_AST_TRANSLATION_UNIT);
|
||||
|
||||
@@ -15,14 +15,14 @@ static void expr_callback(void *context, scc_ast_node_type_t node_type,
|
||||
void *node) {
|
||||
scc_sema_symtab_t *sema_symtab = context;
|
||||
|
||||
if (node_type == SCC_AST_UNKNOWN || node == null) {
|
||||
if (node_type == SCC_AST_UNKNOWN || node == nullptr) {
|
||||
return;
|
||||
}
|
||||
scc_ast_expr_t *expr = SCC_AST_CAST_TO(scc_ast_expr_t, node);
|
||||
if (node_type == SCC_AST_EXPR_IDENTIFIER) {
|
||||
scc_ast_node_t *node =
|
||||
scc_sema_symtab_lookup_symbol(sema_symtab, expr->identifier.name);
|
||||
if (node == null) {
|
||||
if (node == nullptr) {
|
||||
SCC_ERROR(expr->base.loc, "sema error: Identifier '%s' not found",
|
||||
expr->identifier.name);
|
||||
} else if (!SCC_AST_IS_A(scc_ast_decl_t, node)) {
|
||||
@@ -48,7 +48,7 @@ static void stmt_callback(void *context, scc_ast_node_type_t node_type,
|
||||
scc_sema_symtab_leave_scope(sema_symtab);
|
||||
return;
|
||||
}
|
||||
if (node_type == SCC_AST_UNKNOWN || node == null) {
|
||||
if (node_type == SCC_AST_UNKNOWN || node == nullptr) {
|
||||
return;
|
||||
}
|
||||
return;
|
||||
@@ -66,20 +66,20 @@ static void decl_callback(void *context, scc_ast_node_type_t node_type,
|
||||
scc_sema_symtab_leave_scope(sema_symtab);
|
||||
return;
|
||||
}
|
||||
if (node_type == SCC_AST_UNKNOWN || node == null) {
|
||||
if (node_type == SCC_AST_UNKNOWN || node == nullptr) {
|
||||
return;
|
||||
}
|
||||
scc_ast_decl_t *decl = SCC_AST_CAST_TO(scc_ast_decl_t, node);
|
||||
|
||||
scc_ast_type_t *type = scc_malloc(sizeof(scc_ast_type_t));
|
||||
Assert(type != null);
|
||||
Assert(type != nullptr);
|
||||
|
||||
if (node_type == SCC_AST_DECL_STRUCT) {
|
||||
scc_ast_type_struct_init(type, decl->name, decl, decl->base.loc);
|
||||
// FIXME memory leak
|
||||
scc_str_t name = scc_str_from_cstr("$S_");
|
||||
|
||||
if (decl->name == null) {
|
||||
if (decl->name == nullptr) {
|
||||
decl->name = "<anonymous struct>";
|
||||
}
|
||||
scc_str_append_cstr(&name, decl->name, scc_strlen(decl->name));
|
||||
@@ -88,7 +88,7 @@ static void decl_callback(void *context, scc_ast_node_type_t node_type,
|
||||
} else if (node_type == SCC_AST_DECL_UNION) {
|
||||
scc_ast_type_union_init(type, decl->name, decl, decl->base.loc);
|
||||
scc_str_t name = scc_str_from_cstr("$U_");
|
||||
if (decl->name == null) {
|
||||
if (decl->name == nullptr) {
|
||||
decl->name = "<anonymous union>";
|
||||
}
|
||||
scc_str_append_cstr(&name, decl->name, scc_strlen(decl->name));
|
||||
@@ -97,7 +97,7 @@ static void decl_callback(void *context, scc_ast_node_type_t node_type,
|
||||
} else if (node_type == SCC_AST_DECL_ENUM) {
|
||||
scc_ast_type_enum_init(type, decl->name, decl, decl->base.loc);
|
||||
scc_str_t name = scc_str_from_cstr("$E_");
|
||||
if (decl->name == null) {
|
||||
if (decl->name == nullptr) {
|
||||
decl->name = "<anonymous enum>";
|
||||
}
|
||||
scc_str_append_cstr(&name, decl->name, scc_strlen(decl->name));
|
||||
@@ -111,7 +111,7 @@ static void decl_callback(void *context, scc_ast_node_type_t node_type,
|
||||
// LOG_INFO("enum added %s", enum_decl->name);
|
||||
}
|
||||
} else if (node_type == SCC_AST_DECL_TYPEDEF) {
|
||||
if (decl->name == null) {
|
||||
if (decl->name == nullptr) {
|
||||
SCC_ERROR(decl->base.loc, "typedef without name");
|
||||
return;
|
||||
}
|
||||
@@ -120,7 +120,7 @@ static void decl_callback(void *context, scc_ast_node_type_t node_type,
|
||||
} else if (node_type == SCC_AST_DECL_VAR) {
|
||||
scc_sema_symtab_add_symbol(sema_symtab, decl->name, &decl->base);
|
||||
} else if (node_type == SCC_AST_DECL_PARAM) {
|
||||
if (decl->name == null) {
|
||||
if (decl->name == nullptr) {
|
||||
if (decl->param.type->base.type == SCC_AST_TYPE_BUILTIN &&
|
||||
(decl->param.type->builtin.type ==
|
||||
SCC_AST_BUILTIN_TYPE_VA_LIST ||
|
||||
@@ -132,7 +132,7 @@ static void decl_callback(void *context, scc_ast_node_type_t node_type,
|
||||
}
|
||||
scc_sema_symtab_add_symbol(sema_symtab, decl->name, &decl->base);
|
||||
} else if (node_type == SCC_AST_DECL_FUNC) {
|
||||
if (decl->name == null) {
|
||||
if (decl->name == nullptr) {
|
||||
SCC_ERROR(decl->base.loc, "sema error: Function must have a name");
|
||||
} else {
|
||||
// FIXME 重名函数...
|
||||
@@ -150,12 +150,12 @@ static scc_ast_type_t *got_type_callback(void *context, const char *name) {
|
||||
*type = *(scc_ast_type_t *)node;
|
||||
return type;
|
||||
}
|
||||
return null;
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
void scc_sema_init(scc_sema_callbacks_t *callbacks) {
|
||||
scc_sema_symtab_t *sema_symtab = scc_malloc(sizeof(scc_sema_symtab_t));
|
||||
if (sema_symtab == null) {
|
||||
if (sema_symtab == nullptr) {
|
||||
LOG_FATAL("out of memory");
|
||||
return;
|
||||
}
|
||||
@@ -176,15 +176,16 @@ void scc_sema_init(scc_sema_callbacks_t *callbacks) {
|
||||
&type->base);
|
||||
|
||||
scc_ast_decl_t *decl = scc_malloc(sizeof(scc_ast_decl_t));
|
||||
scc_ast_decl_val_init(decl, type, "__scc_builtin__", null,
|
||||
scc_ast_decl_val_init(decl, type, "__scc_builtin__", nullptr,
|
||||
scc_pos_create());
|
||||
scc_sema_symtab_add_symbol(sema_symtab, "__func__", &decl->base);
|
||||
|
||||
scc_ast_type_t *built_func_type = scc_malloc(sizeof(scc_ast_type_t));
|
||||
scc_ast_type_function_init(built_func_type, null, null, scc_pos_create());
|
||||
scc_ast_type_function_init(built_func_type, nullptr, nullptr,
|
||||
scc_pos_create());
|
||||
scc_ast_decl_t *builin_func = scc_malloc(sizeof(scc_ast_decl_t));
|
||||
scc_ast_decl_func_init(builin_func, built_func_type, "__scc_builtin_func",
|
||||
null, scc_pos_create());
|
||||
nullptr, scc_pos_create());
|
||||
scc_sema_symtab_add_symbol(sema_symtab, "__scc_builtin_va_start",
|
||||
&builin_func->base);
|
||||
scc_sema_symtab_add_symbol(sema_symtab, "__scc_builtin_va_end",
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
#include <sema_symtab.h>
|
||||
|
||||
void scc_sema_symtab_init(scc_sema_symtab_t *symtab) {
|
||||
symtab->root_scope.parent = null;
|
||||
symtab->root_scope.parent = nullptr;
|
||||
|
||||
scc_hashtable_init(&symtab->root_scope.symbols,
|
||||
(scc_hashtable_hash_func_t)scc_strhash32,
|
||||
@@ -10,7 +10,7 @@ void scc_sema_symtab_init(scc_sema_symtab_t *symtab) {
|
||||
}
|
||||
|
||||
void scc_sema_symtab_drop(scc_sema_symtab_t *symtab) {
|
||||
while (symtab->current_scope != null) {
|
||||
while (symtab->current_scope != nullptr) {
|
||||
scc_hashtable_drop(&symtab->current_scope->symbols);
|
||||
symtab->current_scope = symtab->current_scope->parent;
|
||||
}
|
||||
@@ -18,7 +18,7 @@ void scc_sema_symtab_drop(scc_sema_symtab_t *symtab) {
|
||||
|
||||
void scc_sema_symtab_enter_scope(scc_sema_symtab_t *symtab) {
|
||||
scc_sema_scope_t *scope = scc_malloc(sizeof(scc_sema_scope_t));
|
||||
if (scope == null) {
|
||||
if (scope == nullptr) {
|
||||
LOG_FATAL("out of memory");
|
||||
return;
|
||||
}
|
||||
@@ -47,13 +47,13 @@ scc_ast_node_t *scc_sema_symtab_add_symbol(scc_sema_symtab_t *symtab,
|
||||
|
||||
scc_ast_node_t *scc_sema_symtab_lookup_symbol(scc_sema_symtab_t *symtab,
|
||||
const char *name) {
|
||||
scc_ast_node_t *node = null;
|
||||
for (scc_sema_scope_t *scope = symtab->current_scope; scope != null;
|
||||
scc_ast_node_t *node = nullptr;
|
||||
for (scc_sema_scope_t *scope = symtab->current_scope; scope != nullptr;
|
||||
scope = scope->parent) {
|
||||
node = scc_hashtable_get(&scope->symbols, name);
|
||||
if (node != null) {
|
||||
if (node != nullptr) {
|
||||
return node;
|
||||
}
|
||||
}
|
||||
return null;
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
@@ -26,7 +26,7 @@ static scc_ast_node_t *process_input(const char *input,
|
||||
scc_sema_init(&sema_callbacks);
|
||||
scc_parser_init(&parser, tok_ring, &sema_callbacks);
|
||||
} else {
|
||||
scc_parser_init(&parser, tok_ring, null);
|
||||
scc_parser_init(&parser, tok_ring, nullptr);
|
||||
}
|
||||
|
||||
scc_ast_node_t *ret = parse_func(&parser);
|
||||
@@ -36,7 +36,7 @@ static scc_ast_node_t *process_input(const char *input,
|
||||
if (not_eof == true) {
|
||||
// FIXME MAYBE free
|
||||
LOG_FATAL("Didn't consume all tokens");
|
||||
return null;
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
scc_lexer_drop_ring(parser.ring);
|
||||
|
||||
@@ -170,14 +170,14 @@ static void test_unary_expr(void) {
|
||||
TEST_CASE("sizeof expression");
|
||||
{
|
||||
scc_ast_expr_t sizeof_expr;
|
||||
scc_ast_expr_sizeof_init(&sizeof_expr, NULL, &x, LOC);
|
||||
scc_ast_expr_sizeof_init(&sizeof_expr, nullptr, &x, LOC);
|
||||
SCC_CHECK_AST(&sizeof_expr.base, "sizeof(x)", scc_parse_expression);
|
||||
}
|
||||
|
||||
TEST_CASE("sizeof type");
|
||||
{
|
||||
scc_ast_expr_t sizeof_type;
|
||||
scc_ast_expr_sizeof_init(&sizeof_type, &int_type, NULL, LOC);
|
||||
scc_ast_expr_sizeof_init(&sizeof_type, &int_type, nullptr, LOC);
|
||||
SCC_CHECK_AST(&sizeof_type.base, "sizeof(int)", scc_parse_expression);
|
||||
}
|
||||
}
|
||||
@@ -391,5 +391,5 @@ TEST_LIST = {
|
||||
{"test_comma_expr", test_comma_expr},
|
||||
{"test_complex_expr", test_complex_expr},
|
||||
{"test_detail_expr", test_detail_expr},
|
||||
{NULL, NULL},
|
||||
{nullptr, nullptr},
|
||||
};
|
||||
|
||||
@@ -106,7 +106,7 @@ static void test_array_type(void) {
|
||||
{
|
||||
// int []
|
||||
scc_ast_type_t array_unknown_int;
|
||||
scc_ast_type_array_init(&array_unknown_int, &int_type, null,
|
||||
scc_ast_type_array_init(&array_unknown_int, &int_type, nullptr,
|
||||
scc_pos_create());
|
||||
SCC_CHECK_AST(&array_unknown_int.base, "int []", scc_parse_type_name);
|
||||
}
|
||||
@@ -159,7 +159,7 @@ static void test_function_type(void) {
|
||||
{
|
||||
// int ()
|
||||
scc_ast_type_t func_type;
|
||||
scc_ast_type_function_init(&func_type, &int_type, null,
|
||||
scc_ast_type_function_init(&func_type, &int_type, nullptr,
|
||||
scc_pos_create());
|
||||
SCC_CHECK_AST(&func_type.base, "int ()", scc_parse_type_name);
|
||||
}
|
||||
@@ -168,7 +168,7 @@ static void test_function_type(void) {
|
||||
{
|
||||
// int (void)
|
||||
scc_ast_decl_t void_param;
|
||||
scc_ast_decl_param_init(&void_param, &void_type, null,
|
||||
scc_ast_decl_param_init(&void_param, &void_type, nullptr,
|
||||
scc_pos_create());
|
||||
|
||||
scc_ast_decl_vec_t params;
|
||||
@@ -189,8 +189,9 @@ static void test_function_type(void) {
|
||||
scc_pos_create());
|
||||
|
||||
scc_ast_decl_t param_int, param_float;
|
||||
scc_ast_decl_param_init(¶m_int, &int_type, null, scc_pos_create());
|
||||
scc_ast_decl_param_init(¶m_float, &float_type, null,
|
||||
scc_ast_decl_param_init(¶m_int, &int_type, nullptr,
|
||||
scc_pos_create());
|
||||
scc_ast_decl_param_init(¶m_float, &float_type, nullptr,
|
||||
scc_pos_create());
|
||||
|
||||
scc_ast_decl_vec_t params;
|
||||
@@ -212,7 +213,8 @@ static void test_function_type(void) {
|
||||
scc_pos_create());
|
||||
|
||||
scc_ast_decl_t param_int, param_var;
|
||||
scc_ast_decl_param_init(¶m_int, &int_type, null, scc_pos_create());
|
||||
scc_ast_decl_param_init(¶m_int, &int_type, nullptr,
|
||||
scc_pos_create());
|
||||
scc_ast_decl_param_init(¶m_var, &va_list_type, "...",
|
||||
scc_pos_create());
|
||||
|
||||
@@ -231,7 +233,7 @@ static void test_function_type(void) {
|
||||
{
|
||||
// int *()
|
||||
scc_ast_type_t func_type;
|
||||
scc_ast_type_function_init(&func_type, &pointer_int_type, null,
|
||||
scc_ast_type_function_init(&func_type, &pointer_int_type, nullptr,
|
||||
scc_pos_create());
|
||||
SCC_CHECK_AST(&func_type.base, "int *()", scc_parse_type_name);
|
||||
}
|
||||
@@ -240,7 +242,7 @@ static void test_function_type(void) {
|
||||
{
|
||||
// int (*)(void)
|
||||
scc_ast_decl_t void_param;
|
||||
scc_ast_decl_param_init(&void_param, &void_type, null,
|
||||
scc_ast_decl_param_init(&void_param, &void_type, nullptr,
|
||||
scc_pos_create());
|
||||
|
||||
scc_ast_decl_vec_t params;
|
||||
@@ -262,7 +264,7 @@ static void test_struct_union_type(void) {
|
||||
{
|
||||
// struct S
|
||||
scc_ast_type_t struct_type;
|
||||
scc_ast_type_struct_init(&struct_type, "S", null, scc_pos_create());
|
||||
scc_ast_type_struct_init(&struct_type, "S", nullptr, scc_pos_create());
|
||||
SCC_CHECK_AST(&struct_type.base, "struct S", scc_parse_type_name);
|
||||
}
|
||||
|
||||
@@ -270,7 +272,7 @@ static void test_struct_union_type(void) {
|
||||
{
|
||||
// union U
|
||||
scc_ast_type_t union_type;
|
||||
scc_ast_type_union_init(&union_type, "U", null, scc_pos_create());
|
||||
scc_ast_type_union_init(&union_type, "U", nullptr, scc_pos_create());
|
||||
SCC_CHECK_AST(&union_type.base, "union U", scc_parse_type_name);
|
||||
}
|
||||
|
||||
@@ -278,17 +280,19 @@ static void test_struct_union_type(void) {
|
||||
{
|
||||
// struct { int x; }
|
||||
scc_ast_decl_t field_x;
|
||||
scc_ast_decl_val_init(&field_x, &int_type, "x", null, scc_pos_create());
|
||||
scc_ast_decl_val_init(&field_x, &int_type, "x", nullptr,
|
||||
scc_pos_create());
|
||||
|
||||
scc_ast_decl_vec_t fields;
|
||||
scc_vec_init(fields);
|
||||
scc_vec_push(fields, &field_x);
|
||||
|
||||
scc_ast_decl_t struct_decl;
|
||||
scc_ast_decl_struct_init(&struct_decl, null, &fields, scc_pos_create());
|
||||
scc_ast_decl_struct_init(&struct_decl, nullptr, &fields,
|
||||
scc_pos_create());
|
||||
|
||||
scc_ast_type_t struct_type;
|
||||
scc_ast_type_struct_init(&struct_type, null, &struct_decl,
|
||||
scc_ast_type_struct_init(&struct_type, nullptr, &struct_decl,
|
||||
scc_pos_create());
|
||||
SCC_CHECK_AST(&struct_type.base, "struct { int x; }",
|
||||
scc_parse_type_name);
|
||||
@@ -298,7 +302,8 @@ static void test_struct_union_type(void) {
|
||||
{
|
||||
// struct S { int x; }
|
||||
scc_ast_decl_t field_x;
|
||||
scc_ast_decl_val_init(&field_x, &int_type, "x", null, scc_pos_create());
|
||||
scc_ast_decl_val_init(&field_x, &int_type, "x", nullptr,
|
||||
scc_pos_create());
|
||||
|
||||
scc_ast_decl_vec_t fields;
|
||||
scc_vec_init(fields);
|
||||
@@ -322,8 +327,9 @@ static void test_struct_union_type(void) {
|
||||
scc_pos_create());
|
||||
|
||||
scc_ast_decl_t field_a, field_b;
|
||||
scc_ast_decl_val_init(&field_a, &int_type, "a", null, scc_pos_create());
|
||||
scc_ast_decl_val_init(&field_b, &float_type, "b", null,
|
||||
scc_ast_decl_val_init(&field_a, &int_type, "a", nullptr,
|
||||
scc_pos_create());
|
||||
scc_ast_decl_val_init(&field_b, &float_type, "b", nullptr,
|
||||
scc_pos_create());
|
||||
|
||||
scc_ast_decl_vec_t fields;
|
||||
@@ -332,10 +338,11 @@ static void test_struct_union_type(void) {
|
||||
scc_vec_push(fields, &field_b);
|
||||
|
||||
scc_ast_decl_t union_decl;
|
||||
scc_ast_decl_union_init(&union_decl, null, &fields, scc_pos_create());
|
||||
scc_ast_decl_union_init(&union_decl, nullptr, &fields,
|
||||
scc_pos_create());
|
||||
|
||||
scc_ast_type_t union_type;
|
||||
scc_ast_type_union_init(&union_type, null, &union_decl,
|
||||
scc_ast_type_union_init(&union_type, nullptr, &union_decl,
|
||||
scc_pos_create());
|
||||
SCC_CHECK_AST(&union_type.base, "union { int a; float b; }",
|
||||
scc_parse_type_name);
|
||||
@@ -347,7 +354,7 @@ static void test_enum_type(void) {
|
||||
{
|
||||
// enum E
|
||||
scc_ast_type_t enum_type;
|
||||
scc_ast_type_enum_init(&enum_type, "E", null, scc_pos_create());
|
||||
scc_ast_type_enum_init(&enum_type, "E", nullptr, scc_pos_create());
|
||||
SCC_CHECK_AST(&enum_type.base, "enum E", scc_parse_type_name);
|
||||
}
|
||||
|
||||
@@ -357,10 +364,11 @@ static void test_enum_type(void) {
|
||||
scc_ast_type_t enum_type;
|
||||
|
||||
scc_ast_decl_t red, green, blue;
|
||||
scc_ast_decl_val_init(&red, &enum_type, "RED", null, scc_pos_create());
|
||||
scc_ast_decl_val_init(&green, &enum_type, "GREEN", null,
|
||||
scc_ast_decl_val_init(&red, &enum_type, "RED", nullptr,
|
||||
scc_pos_create());
|
||||
scc_ast_decl_val_init(&blue, &enum_type, "BLUE", null,
|
||||
scc_ast_decl_val_init(&green, &enum_type, "GREEN", nullptr,
|
||||
scc_pos_create());
|
||||
scc_ast_decl_val_init(&blue, &enum_type, "BLUE", nullptr,
|
||||
scc_pos_create());
|
||||
|
||||
scc_ast_decl_vec_t enumerators;
|
||||
@@ -370,10 +378,11 @@ static void test_enum_type(void) {
|
||||
scc_vec_push(enumerators, &blue);
|
||||
|
||||
scc_ast_decl_t enum_decl;
|
||||
scc_ast_decl_enum_init(&enum_decl, null, &enumerators,
|
||||
scc_ast_decl_enum_init(&enum_decl, nullptr, &enumerators,
|
||||
scc_pos_create());
|
||||
|
||||
scc_ast_type_enum_init(&enum_type, null, &enum_decl, scc_pos_create());
|
||||
scc_ast_type_enum_init(&enum_type, nullptr, &enum_decl,
|
||||
scc_pos_create());
|
||||
SCC_CHECK_AST(&enum_type.base, "enum { RED, GREEN, BLUE }",
|
||||
scc_parse_type_name);
|
||||
}
|
||||
@@ -384,10 +393,11 @@ static void test_enum_type(void) {
|
||||
scc_ast_type_t enum_type;
|
||||
|
||||
scc_ast_decl_t red, green, blue;
|
||||
scc_ast_decl_val_init(&red, &enum_type, "RED", null, scc_pos_create());
|
||||
scc_ast_decl_val_init(&green, &enum_type, "GREEN", null,
|
||||
scc_ast_decl_val_init(&red, &enum_type, "RED", nullptr,
|
||||
scc_pos_create());
|
||||
scc_ast_decl_val_init(&blue, &enum_type, "BLUE", null,
|
||||
scc_ast_decl_val_init(&green, &enum_type, "GREEN", nullptr,
|
||||
scc_pos_create());
|
||||
scc_ast_decl_val_init(&blue, &enum_type, "BLUE", nullptr,
|
||||
scc_pos_create());
|
||||
|
||||
scc_ast_decl_vec_t enumerators;
|
||||
@@ -397,7 +407,7 @@ static void test_enum_type(void) {
|
||||
scc_vec_push(enumerators, &blue);
|
||||
|
||||
scc_ast_decl_t enum_decl;
|
||||
scc_ast_decl_enum_init(&enum_decl, null, &enumerators,
|
||||
scc_ast_decl_enum_init(&enum_decl, nullptr, &enumerators,
|
||||
scc_pos_create());
|
||||
|
||||
scc_ast_type_enum_init(&enum_type, "E", &enum_decl, scc_pos_create());
|
||||
@@ -485,7 +495,7 @@ static void test_hard_type(void) {
|
||||
{
|
||||
// 1) 函数类型 int (void)
|
||||
scc_ast_decl_t void_param;
|
||||
scc_ast_decl_param_init(&void_param, &void_type, null,
|
||||
scc_ast_decl_param_init(&void_param, &void_type, nullptr,
|
||||
scc_pos_create());
|
||||
scc_ast_decl_vec_t params;
|
||||
scc_vec_init(params);
|
||||
@@ -533,7 +543,7 @@ static void test_hard_type(void) {
|
||||
|
||||
// 3) 函数类型,返回上述指针,无参数
|
||||
scc_ast_decl_t void_param;
|
||||
scc_ast_decl_param_init(&void_param, &void_type, null,
|
||||
scc_ast_decl_param_init(&void_param, &void_type, nullptr,
|
||||
scc_pos_create());
|
||||
scc_ast_decl_vec_t params;
|
||||
scc_vec_init(params);
|
||||
@@ -556,7 +566,7 @@ static void test_hard_type(void) {
|
||||
{
|
||||
// 1) 函数类型 int (void)
|
||||
scc_ast_decl_t void_param;
|
||||
scc_ast_decl_param_init(&void_param, &void_type, null,
|
||||
scc_ast_decl_param_init(&void_param, &void_type, nullptr,
|
||||
scc_pos_create());
|
||||
scc_ast_decl_vec_t params;
|
||||
scc_vec_init(params);
|
||||
@@ -572,7 +582,7 @@ static void test_hard_type(void) {
|
||||
|
||||
// 3) 外部函数类型,返回上述指针,无参数
|
||||
scc_ast_type_t outer_func;
|
||||
scc_ast_type_function_init(&outer_func, &ptr_to_func, null,
|
||||
scc_ast_type_function_init(&outer_func, &ptr_to_func, nullptr,
|
||||
scc_pos_create());
|
||||
|
||||
SCC_CHECK_AST(&outer_func.base, "int (*())(void)", scc_parse_type_name);
|
||||
@@ -588,5 +598,5 @@ TEST_LIST = {
|
||||
{"test_enum_type", test_enum_type},
|
||||
{"test_specifier_type", test_specifier_type},
|
||||
{"test_hard_type", test_hard_type},
|
||||
{null, null},
|
||||
{nullptr, nullptr},
|
||||
};
|
||||
|
||||
@@ -32,7 +32,7 @@ static void test_parser_unit(void) {
|
||||
// 1. 变量声明 int a;
|
||||
{
|
||||
scc_ast_decl_t int_decl;
|
||||
scc_ast_decl_val_init(&int_decl, &int_type, "a", null,
|
||||
scc_ast_decl_val_init(&int_decl, &int_type, "a", nullptr,
|
||||
scc_pos_create());
|
||||
SCC_CHECK_AST(&int_decl.base, "int a;", scc_parse_declaration);
|
||||
}
|
||||
@@ -43,14 +43,15 @@ static void test_parser_unit(void) {
|
||||
scc_ast_type_t func_type;
|
||||
scc_ast_decl_vec_t func_params;
|
||||
scc_ast_decl_t void_decl;
|
||||
scc_ast_decl_param_init(&void_decl, &void_type, null, scc_pos_create());
|
||||
scc_ast_decl_param_init(&void_decl, &void_type, nullptr,
|
||||
scc_pos_create());
|
||||
scc_ast_decl_t *array[] = {&void_decl};
|
||||
scc_vec_unsafe_from_static_array(func_params, array);
|
||||
scc_ast_type_function_init(&func_type, &int_type, &func_params,
|
||||
scc_pos_create());
|
||||
// 构造复合语句块(空)
|
||||
scc_ast_stmt_t compound;
|
||||
scc_ast_stmt_compound_init(&compound, null, scc_pos_create());
|
||||
scc_ast_stmt_compound_init(&compound, nullptr, scc_pos_create());
|
||||
|
||||
// 构造函数声明
|
||||
scc_ast_decl_t func_decl;
|
||||
@@ -66,14 +67,15 @@ static void test_parser_unit(void) {
|
||||
scc_ast_type_t func_type;
|
||||
scc_ast_decl_vec_t func_params;
|
||||
scc_ast_decl_t void_decl;
|
||||
scc_ast_decl_param_init(&void_decl, &void_type, null, scc_pos_create());
|
||||
scc_ast_decl_param_init(&void_decl, &void_type, nullptr,
|
||||
scc_pos_create());
|
||||
scc_ast_decl_t *array[] = {&void_decl};
|
||||
scc_vec_unsafe_from_static_array(func_params, array);
|
||||
scc_ast_type_function_init(&func_type, &int_type, &func_params,
|
||||
scc_pos_create());
|
||||
|
||||
scc_ast_stmt_t compound;
|
||||
scc_ast_stmt_compound_init(&compound, null, scc_pos_create());
|
||||
scc_ast_stmt_compound_init(&compound, nullptr, scc_pos_create());
|
||||
|
||||
scc_ast_decl_t func_decl;
|
||||
scc_ast_decl_func_init(&func_decl, &func_type, "main", &compound,
|
||||
@@ -114,7 +116,8 @@ static void test_parser_unit(void) {
|
||||
scc_ast_type_t func_type;
|
||||
scc_ast_decl_vec_t func_params;
|
||||
scc_ast_decl_t void_decl;
|
||||
scc_ast_decl_param_init(&void_decl, &void_type, null, scc_pos_create());
|
||||
scc_ast_decl_param_init(&void_decl, &void_type, nullptr,
|
||||
scc_pos_create());
|
||||
scc_ast_decl_t *array[] = {&void_decl};
|
||||
scc_vec_unsafe_from_static_array(func_params, array);
|
||||
scc_ast_type_function_init(&func_type, &int_type, &func_params,
|
||||
@@ -139,11 +142,13 @@ static void test_parser_unit(void) {
|
||||
{
|
||||
// 变量声明 int a;
|
||||
scc_ast_decl_t a_decl;
|
||||
scc_ast_decl_val_init(&a_decl, &int_type, "a", null, scc_pos_create());
|
||||
scc_ast_decl_val_init(&a_decl, &int_type, "a", nullptr,
|
||||
scc_pos_create());
|
||||
|
||||
// 变量声明 int b;
|
||||
scc_ast_decl_t b_decl;
|
||||
scc_ast_decl_val_init(&b_decl, &int_type, "b", null, scc_pos_create());
|
||||
scc_ast_decl_val_init(&b_decl, &int_type, "b", nullptr,
|
||||
scc_pos_create());
|
||||
|
||||
// 表达式 1 + 2 * 3
|
||||
scc_ast_expr_t lit1, lit2, lit3, mul, add;
|
||||
@@ -213,7 +218,7 @@ static void test_parser_unit(void) {
|
||||
// 函数类型
|
||||
scc_ast_type_t func_type;
|
||||
scc_ast_type_function_init(&func_type, (scc_ast_type_t *)&int_type,
|
||||
null, scc_pos_create());
|
||||
nullptr, scc_pos_create());
|
||||
|
||||
scc_ast_decl_t func_decl;
|
||||
scc_ast_decl_func_init(&func_decl, &func_type, "main", &compound,
|
||||
@@ -284,8 +289,8 @@ static void test_parser_unit(void) {
|
||||
// 函数类型(返回 int,无参数)
|
||||
scc_ast_type_t func_type;
|
||||
scc_ast_type_function_init(&func_type, (scc_ast_type_t *)&int_type,
|
||||
null,
|
||||
scc_pos_create()); // null 表示无参数
|
||||
nullptr,
|
||||
scc_pos_create()); // nullptr 表示无参数
|
||||
|
||||
// 函数声明 int main() { ... }
|
||||
scc_ast_decl_t func_decl;
|
||||
@@ -320,15 +325,15 @@ static void test_parser_unit(void) {
|
||||
scc_ast_decl_param_init(¶m1, (scc_ast_type_t *)&int_type, "b",
|
||||
scc_pos_create());
|
||||
scc_ast_decl_t param2;
|
||||
scc_ast_decl_param_init(¶m2, (scc_ast_type_t *)&va_list_type, null,
|
||||
scc_pos_create());
|
||||
scc_ast_decl_param_init(¶m2, (scc_ast_type_t *)&va_list_type,
|
||||
nullptr, scc_pos_create());
|
||||
scc_ast_decl_t *params_array[] = {¶m0, ¶m1, ¶m2};
|
||||
scc_vec_unsafe_from_static_array(params, params_array);
|
||||
scc_ast_type_t decl_func_type;
|
||||
scc_ast_type_function_init(&decl_func_type, (scc_ast_type_t *)&int_type,
|
||||
¶ms, scc_pos_create());
|
||||
scc_ast_decl_t decl_func;
|
||||
scc_ast_decl_func_init(&decl_func, &decl_func_type, "add", null,
|
||||
scc_ast_decl_func_init(&decl_func, &decl_func_type, "add", nullptr,
|
||||
scc_pos_create());
|
||||
SCC_CHECK_AST(&decl_func.base, "int add(int a, int b, ...);",
|
||||
scc_parse_declaration);
|
||||
@@ -343,7 +348,7 @@ static void test_parser_unit(void) {
|
||||
scc_pos_create());
|
||||
|
||||
scc_ast_decl_t i32a_decl;
|
||||
scc_ast_decl_val_init(&i32a_decl, &typedef_type, "a", null,
|
||||
scc_ast_decl_val_init(&i32a_decl, &typedef_type, "a", nullptr,
|
||||
scc_pos_create());
|
||||
|
||||
scc_ast_node_t *array[] = {&typedef_decl.base, &i32a_decl.base};
|
||||
@@ -364,7 +369,7 @@ static void test_parser_unit(void) {
|
||||
scc_pos_create());
|
||||
|
||||
scc_ast_decl_t void_ptr_a_decl;
|
||||
scc_ast_decl_val_init(&void_ptr_a_decl, &void_ptr_type, "a", null,
|
||||
scc_ast_decl_val_init(&void_ptr_a_decl, &void_ptr_type, "a", nullptr,
|
||||
scc_pos_create());
|
||||
|
||||
scc_ast_node_t *array2[] = {&void_ptr_decl.base, &void_ptr_a_decl.base};
|
||||
@@ -381,19 +386,20 @@ static void test_parser_unit(void) {
|
||||
{
|
||||
// struct { int x; } (匿名结构体定义)
|
||||
scc_ast_decl_t field;
|
||||
scc_ast_decl_val_init(&field, (scc_ast_type_t *)&int_type, "x", null,
|
||||
scc_ast_decl_val_init(&field, (scc_ast_type_t *)&int_type, "x", nullptr,
|
||||
scc_pos_create());
|
||||
scc_ast_decl_vec_t fields;
|
||||
scc_vec_init(fields);
|
||||
scc_vec_push(fields, &field);
|
||||
|
||||
scc_ast_decl_t struct_def;
|
||||
scc_ast_decl_struct_init(&struct_def, null, &fields, scc_pos_create());
|
||||
scc_ast_decl_struct_init(&struct_def, nullptr, &fields,
|
||||
scc_pos_create());
|
||||
SCC_CHECK_AST(&struct_def.base, "struct { int x;};",
|
||||
scc_parse_declaration);
|
||||
|
||||
scc_ast_type_t struct_type;
|
||||
scc_ast_type_struct_init(&struct_type, null, &struct_def,
|
||||
scc_ast_type_struct_init(&struct_type, nullptr, &struct_def,
|
||||
scc_pos_create());
|
||||
scc_ast_type_t typedef_type;
|
||||
scc_ast_type_typedef_init(&typedef_type, "struct_t", &struct_def,
|
||||
@@ -406,7 +412,7 @@ static void test_parser_unit(void) {
|
||||
scc_parse_declaration);
|
||||
|
||||
scc_ast_decl_t typedef_impl_decl;
|
||||
scc_ast_decl_val_init(&typedef_impl_decl, &typedef_type, "a", null,
|
||||
scc_ast_decl_val_init(&typedef_impl_decl, &typedef_type, "a", nullptr,
|
||||
scc_pos_create());
|
||||
scc_ast_node_t *array[] = {&typedef_decl.base, &typedef_impl_decl.base};
|
||||
scc_ast_stmt_t stmt;
|
||||
@@ -431,7 +437,8 @@ static void test_parser_unit(void) {
|
||||
scc_ast_decl_t param2;
|
||||
scc_ast_decl_param_init(¶m2, &int_type, "b", scc_pos_create());
|
||||
scc_ast_decl_t param3;
|
||||
scc_ast_decl_param_init(¶m3, &va_list_type, null, scc_pos_create());
|
||||
scc_ast_decl_param_init(¶m3, &va_list_type, nullptr,
|
||||
scc_pos_create());
|
||||
scc_ast_decl_t *params_array[] = {¶m1, ¶m2, ¶m3};
|
||||
scc_ast_decl_vec_t func_params;
|
||||
scc_vec_unsafe_from_static_array(func_params, params_array);
|
||||
@@ -443,7 +450,7 @@ static void test_parser_unit(void) {
|
||||
scc_ast_type_function_init(&func_type, &return_type, &func_params,
|
||||
scc_pos_create());
|
||||
scc_ast_decl_t func_decl;
|
||||
scc_ast_decl_func_init(&func_decl, &func_type, "func", null,
|
||||
scc_ast_decl_func_init(&func_decl, &func_type, "func", nullptr,
|
||||
scc_pos_create());
|
||||
|
||||
scc_ast_decl_t *decls_array[] = {&type_decl, &func_decl};
|
||||
@@ -512,7 +519,7 @@ static void test_parser_unit(void) {
|
||||
|
||||
// 6. 函数声明
|
||||
scc_ast_decl_t decl;
|
||||
scc_ast_decl_func_init(&decl, &func_type, "call", null,
|
||||
scc_ast_decl_func_init(&decl, &func_type, "call", nullptr,
|
||||
scc_pos_create());
|
||||
|
||||
// 7. 与解析结果比较
|
||||
@@ -664,9 +671,9 @@ static void test_parser_unit(void) {
|
||||
{
|
||||
scc_ast_decl_t decl_a, decl_b;
|
||||
scc_ast_decl_val_init(&decl_a, (scc_ast_type_t *)&int_type, "a",
|
||||
null, scc_pos_create());
|
||||
nullptr, scc_pos_create());
|
||||
scc_ast_decl_val_init(&decl_b, (scc_ast_type_t *)&int_type, "b",
|
||||
null, scc_pos_create());
|
||||
nullptr, scc_pos_create());
|
||||
|
||||
scc_ast_decl_vec_t decl_vec;
|
||||
scc_vec_init(decl_vec);
|
||||
@@ -708,7 +715,7 @@ static void test_parser_unit(void) {
|
||||
{
|
||||
// 构造 struct list_head 类型(不完整)
|
||||
scc_ast_type_t struct_list_head;
|
||||
scc_ast_type_struct_init(&struct_list_head, "list_head", null,
|
||||
scc_ast_type_struct_init(&struct_list_head, "list_head", nullptr,
|
||||
scc_pos_create());
|
||||
|
||||
// 构造两个指针类型(分别用于 next 和 prev,指向同一结构体)
|
||||
@@ -720,9 +727,9 @@ static void test_parser_unit(void) {
|
||||
|
||||
// 构造变量声明 next 和 prev
|
||||
scc_ast_decl_t next_decl, prev_decl;
|
||||
scc_ast_decl_val_init(&next_decl, &ptr_to_struct1, "next", null,
|
||||
scc_ast_decl_val_init(&next_decl, &ptr_to_struct1, "next", nullptr,
|
||||
scc_pos_create());
|
||||
scc_ast_decl_val_init(&prev_decl, &ptr_to_struct2, "prev", null,
|
||||
scc_ast_decl_val_init(&prev_decl, &ptr_to_struct2, "prev", nullptr,
|
||||
scc_pos_create());
|
||||
|
||||
// 构造声明列表
|
||||
@@ -742,7 +749,7 @@ static void test_parser_unit(void) {
|
||||
// 构造字段 int a;
|
||||
scc_ast_decl_t field_a;
|
||||
scc_ast_decl_val_init(&field_a, (scc_ast_type_t *)&int_type, "a",
|
||||
null, scc_pos_create());
|
||||
nullptr, scc_pos_create());
|
||||
|
||||
scc_ast_decl_vec_t fields;
|
||||
scc_vec_init(fields);
|
||||
@@ -750,12 +757,12 @@ static void test_parser_unit(void) {
|
||||
|
||||
// 构造匿名结构体定义声明
|
||||
scc_ast_decl_t struct_def;
|
||||
scc_ast_decl_struct_init(&struct_def, null, &fields,
|
||||
scc_ast_decl_struct_init(&struct_def, nullptr, &fields,
|
||||
scc_pos_create()); // fields 被移动
|
||||
|
||||
// 构造匿名结构体类型
|
||||
scc_ast_type_t anon_struct_type;
|
||||
scc_ast_type_struct_init(&anon_struct_type, null, &struct_def,
|
||||
scc_ast_type_struct_init(&anon_struct_type, nullptr, &struct_def,
|
||||
scc_pos_create());
|
||||
|
||||
// 构造指针类型指向该匿名结构体
|
||||
@@ -807,7 +814,8 @@ static void test_parser_unit(void) {
|
||||
scc_ast_type_t func_type;
|
||||
scc_ast_decl_vec_t func_params;
|
||||
scc_ast_decl_t void_decl;
|
||||
scc_ast_decl_param_init(&void_decl, &void_type, null, scc_pos_create());
|
||||
scc_ast_decl_param_init(&void_decl, &void_type, nullptr,
|
||||
scc_pos_create());
|
||||
scc_ast_decl_t *array[] = {&void_decl};
|
||||
scc_vec_unsafe_from_static_array(func_params, array);
|
||||
scc_ast_type_function_init(&func_type, &ptr_to_array, &func_params,
|
||||
@@ -818,7 +826,7 @@ static void test_parser_unit(void) {
|
||||
scc_ast_type_pointer_init(&ptr_to_func, &func_type, scc_pos_create());
|
||||
|
||||
scc_ast_decl_t ptr_to_func_decl;
|
||||
scc_ast_decl_val_init(&ptr_to_func_decl, &ptr_to_func, "foo", null,
|
||||
scc_ast_decl_val_init(&ptr_to_func_decl, &ptr_to_func, "foo", nullptr,
|
||||
scc_pos_create());
|
||||
SCC_CHECK_AST(&ptr_to_func_decl.base, "int (*(*foo)(void))[5];",
|
||||
scc_parse_declaration);
|
||||
@@ -838,13 +846,14 @@ static void test_parser_unit(void) {
|
||||
scc_ast_decl_param_init(¶m2, &typedef_func_type, "a",
|
||||
scc_pos_create());
|
||||
scc_ast_decl_t param3;
|
||||
scc_ast_decl_param_init(¶m1, &va_list_type, null, scc_pos_create());
|
||||
scc_ast_decl_param_init(¶m1, &va_list_type, nullptr,
|
||||
scc_pos_create());
|
||||
scc_ast_decl_t *func_hard_array[] = {¶m1, ¶m2, ¶m3};
|
||||
scc_ast_decl_vec_t func_hard_params;
|
||||
scc_vec_unsafe_from_static_array(func_hard_params, func_hard_array);
|
||||
scc_ast_type_function_init(&func_hard_type, &ptr_to_array,
|
||||
&func_hard_params, scc_pos_create());
|
||||
scc_ast_decl_func_init(&func_hard_decl, &func_hard_type, "bar", null,
|
||||
scc_ast_decl_func_init(&func_hard_decl, &func_hard_type, "bar", nullptr,
|
||||
scc_pos_create());
|
||||
|
||||
scc_ast_decl_vec_t decls;
|
||||
@@ -865,5 +874,5 @@ static void test_parser_unit(void) {
|
||||
|
||||
TEST_LIST = {
|
||||
{"parser_unit", test_parser_unit},
|
||||
{null, null},
|
||||
{nullptr, nullptr},
|
||||
};
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
#include <utest/acutest.h>
|
||||
|
||||
TEST_LIST = {
|
||||
{NULL, NULL},
|
||||
{nullptr, nullptr},
|
||||
};
|
||||
@@ -33,7 +33,7 @@ typedef struct scc_macro_table {
|
||||
* @brief 创建宏对象
|
||||
* @param name 宏名称
|
||||
* @param type 宏类型
|
||||
* @return 创建的宏对象指针,失败返回NULL
|
||||
* @return 创建的宏对象指针,失败返回nullptr
|
||||
*/
|
||||
scc_pproc_macro_t *scc_pproc_macro_new(const scc_str_t *name,
|
||||
scc_pproc_macro_type_t type);
|
||||
@@ -81,7 +81,7 @@ scc_pproc_macro_t *scc_pproc_macro_table_set(scc_pproc_macro_table_t *pp,
|
||||
* @brief 查找宏定义
|
||||
* @param pp 预处理器实例
|
||||
* @param name 宏名称
|
||||
* @return 找到的宏对象指针,未找到返回NULL
|
||||
* @return 找到的宏对象指针,未找到返回nullptr
|
||||
*/
|
||||
scc_pproc_macro_t *scc_pproc_macro_table_get(scc_pproc_macro_table_t *pp,
|
||||
const scc_str_t *name);
|
||||
|
||||
@@ -49,7 +49,7 @@ static inline int keyword_cmp(const char *name, int len) {
|
||||
|
||||
void scc_pproc_parse_macro_arguments(scc_lexer_tok_ring_t *ring,
|
||||
scc_lexer_tok_vec_t *args, int need_full) {
|
||||
Assert(ring != null && args != null);
|
||||
Assert(ring != nullptr && args != nullptr);
|
||||
scc_lexer_tok_t tok = {0};
|
||||
int depth = 0;
|
||||
int ok;
|
||||
@@ -337,7 +337,7 @@ void scc_pproc_handle_directive(scc_pproc_t *pp) {
|
||||
case SCC_PP_TOK_ELSE:
|
||||
case SCC_PP_TOK_ENDIF: {
|
||||
scc_lexer_tok_drop(&tok);
|
||||
scc_pproc_parse_if_defined(pp, type, null);
|
||||
scc_pproc_parse_if_defined(pp, type, nullptr);
|
||||
scc_lexer_skip_until_newline(pp->cur_ring);
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -22,7 +22,7 @@ static scc_lexer_tok_t stringify_argument(scc_pproc_expand_t *ctx,
|
||||
scc_str_append_ch(&str, '\"'); // 左引号
|
||||
|
||||
int need_space = 0; // 是否需要插入空格
|
||||
scc_lexer_tok_t *tok = null;
|
||||
scc_lexer_tok_t *tok = nullptr;
|
||||
scc_vec_foreach(*arg_tokens, i) {
|
||||
tok = &scc_vec_at(*arg_tokens, i);
|
||||
if (tok->type == SCC_TOK_BLANK) {
|
||||
@@ -61,10 +61,10 @@ static scc_lexer_tok_t concatenate_tokens(scc_pproc_expand_t *ctx,
|
||||
const scc_lexer_tok_t *left,
|
||||
const scc_lexer_tok_t *right) {
|
||||
scc_str_t new_lex = scc_str_from_cstr("");
|
||||
if (left != null) {
|
||||
if (left != nullptr) {
|
||||
scc_str_append(&new_lex, &left->lexeme);
|
||||
}
|
||||
if (right != null) {
|
||||
if (right != nullptr) {
|
||||
scc_str_append(&new_lex, &right->lexeme);
|
||||
}
|
||||
|
||||
@@ -154,7 +154,7 @@ void scc_pproc_expand_by_src(scc_pproc_macro_table_t *macro_table,
|
||||
scc_lexer_tok_vec_t output_vec;
|
||||
scc_pproc_expand_by_vec(macro_table, &expaned_buffer, &output_vec, false,
|
||||
need_keep_org_pos);
|
||||
Assert(output->cap == 0 && output->data == null); // FIXME hack it
|
||||
Assert(output->cap == 0 && output->data == nullptr); // FIXME hack it
|
||||
*output = scc_lexer_array_to_ring(&output_vec);
|
||||
}
|
||||
|
||||
@@ -186,7 +186,7 @@ static void disable(scc_pproc_expand_t *expand_ctx,
|
||||
const scc_pproc_macro_t *macro) {
|
||||
scc_pproc_macro_t *expanded_macro =
|
||||
scc_pproc_macro_new(¯o->name, macro->type);
|
||||
if (expanded_macro == null) {
|
||||
if (expanded_macro == nullptr) {
|
||||
LOG_FATAL("Out of memory");
|
||||
}
|
||||
scc_pproc_macro_table_set(expand_ctx->expanded_set, expanded_macro);
|
||||
@@ -200,7 +200,7 @@ static void enable(scc_pproc_expand_t *expand_ctx,
|
||||
static cbool need_skip(scc_pproc_expand_t *expand_ctx,
|
||||
const scc_pproc_macro_t *macro) {
|
||||
return scc_pproc_macro_table_get(expand_ctx->expanded_set, ¯o->name) !=
|
||||
null;
|
||||
nullptr;
|
||||
}
|
||||
|
||||
static inline void
|
||||
@@ -322,7 +322,7 @@ static void rescan(scc_pproc_expand_t *expand_ctx,
|
||||
|
||||
scc_pproc_macro_t *end_macro =
|
||||
scc_pproc_macro_table_get(expand_ctx->macro_table, &end_tok->lexeme);
|
||||
if (end_macro == null || end_macro->type != SCC_PP_MACRO_FUNCTION) {
|
||||
if (end_macro == nullptr || end_macro->type != SCC_PP_MACRO_FUNCTION) {
|
||||
goto RETURN;
|
||||
}
|
||||
|
||||
@@ -387,12 +387,12 @@ static void concact(scc_pproc_expand_t *ctx, scc_lexer_tok_vec_t *tok_buffer,
|
||||
|
||||
scc_lexer_tok_t *left;
|
||||
if (left_idx < 0) {
|
||||
left = null;
|
||||
left = nullptr;
|
||||
left_idx = 0; // FIXME for free tok_buffer
|
||||
} else {
|
||||
left = &scc_vec_at(*tok_buffer, left_idx);
|
||||
if (gnu_va_arg_extend && left->type == SCC_TOK_COMMA) {
|
||||
left = null;
|
||||
left = nullptr;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -468,7 +468,7 @@ static inline void expand_function_macro(scc_pproc_expand_t *ctx,
|
||||
|
||||
scc_lexer_tok_t *right_tok;
|
||||
if (right_idx >= (int)scc_vec_size(macro->replaces)) {
|
||||
right_tok = null;
|
||||
right_tok = nullptr;
|
||||
} else {
|
||||
right_tok = &scc_vec_at(macro->replaces, right_idx);
|
||||
}
|
||||
@@ -488,7 +488,7 @@ static inline void expand_function_macro(scc_pproc_expand_t *ctx,
|
||||
}
|
||||
|
||||
scc_lexer_tok_t *right =
|
||||
scc_vec_size(right_vec) ? &scc_vec_at(right_vec, 0) : null;
|
||||
scc_vec_size(right_vec) ? &scc_vec_at(right_vec, 0) : nullptr;
|
||||
|
||||
// GNU ## extention
|
||||
if (scc_strcmp(scc_str_as_cstr(&(right_tok->lexeme)),
|
||||
@@ -559,7 +559,7 @@ static inline void expand_object_macro(scc_pproc_expand_t *ctx,
|
||||
|
||||
scc_lexer_tok_t *right;
|
||||
if (right_idx >= (int)scc_vec_size(macro->replaces)) {
|
||||
right = null;
|
||||
right = nullptr;
|
||||
} else {
|
||||
right = &scc_vec_at(macro->replaces, right_idx);
|
||||
}
|
||||
@@ -588,7 +588,7 @@ static cbool parse_defined(scc_pproc_expand_t *expand_ctx, scc_pos_t *tok_pos) {
|
||||
}
|
||||
|
||||
if (scc_pproc_macro_table_get(expand_ctx->macro_table,
|
||||
&next_tok.lexeme) == null) {
|
||||
&next_tok.lexeme) == nullptr) {
|
||||
scc_lexer_tok_drop(&next_tok);
|
||||
scc_lexer_gen_number_false(&next_tok);
|
||||
} else {
|
||||
@@ -609,7 +609,7 @@ static cbool parse_defined(scc_pproc_expand_t *expand_ctx, scc_pos_t *tok_pos) {
|
||||
} else if (scc_get_tok_subtype(next_tok.type) ==
|
||||
SCC_TOK_SUBTYPE_IDENTIFIER) {
|
||||
if (scc_pproc_macro_table_get(expand_ctx->macro_table,
|
||||
&next_tok.lexeme) == null) {
|
||||
&next_tok.lexeme) == nullptr) {
|
||||
scc_lexer_tok_drop(&next_tok);
|
||||
scc_lexer_gen_number_false(&next_tok);
|
||||
} else {
|
||||
@@ -649,7 +649,7 @@ void scc_pproc_expand_macro(scc_pproc_expand_t *expand_ctx) {
|
||||
scc_pproc_macro_t *macro =
|
||||
scc_pproc_macro_table_get(expand_ctx->macro_table, &tok.lexeme);
|
||||
|
||||
if (macro == null || 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
|
||||
tok.type += SCC_TOK_DISABLED;
|
||||
scc_vec_push(expand_ctx->output, tok);
|
||||
|
||||
@@ -83,7 +83,7 @@ cbool scc_pproc_parse_if_defined(scc_pproc_t *pp, scc_tok_type_t type,
|
||||
int defined = 0;
|
||||
if (tok) {
|
||||
defined = (scc_pproc_macro_table_get(&pp->macro_table,
|
||||
&(tok->lexeme)) != null);
|
||||
&(tok->lexeme)) != nullptr);
|
||||
}
|
||||
switch (type) {
|
||||
case SCC_PP_TOK_IFDEF:
|
||||
|
||||
@@ -43,7 +43,7 @@ FOPEN:
|
||||
}
|
||||
|
||||
scc_pproc_file_t *file = scc_malloc(sizeof(scc_pproc_file_t));
|
||||
Assert(file != null);
|
||||
Assert(file != nullptr);
|
||||
if (scc_sstream_init(&(file->sstream), scc_str_as_cstr(&fpath), 1024)) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
@@ -6,7 +6,7 @@ scc_pproc_macro_t *scc_pproc_macro_new(const scc_str_t *name,
|
||||
scc_pproc_macro_t *macro = scc_malloc(sizeof(scc_pproc_macro_t));
|
||||
if (!macro) {
|
||||
LOG_ERROR("Failed to allocate memory for macro");
|
||||
return null;
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
macro->name = scc_str_copy(name);
|
||||
@@ -96,7 +96,7 @@ cbool scc_pproc_add_function_macro(scc_pproc_macro_table_t *macros,
|
||||
|
||||
scc_pproc_macro_t *scc_pproc_macro_table_set(scc_pproc_macro_table_t *pp,
|
||||
scc_pproc_macro_t *macro) {
|
||||
Assert(pp != null && macro != null && scc_str_len(¯o->name) != 0);
|
||||
Assert(pp != nullptr && macro != nullptr && scc_str_len(¯o->name) != 0);
|
||||
scc_pproc_macro_t *old = scc_hashtable_set(&pp->table, ¯o->name, macro);
|
||||
if (old && old != macro) {
|
||||
LOG_WARN("same macro name `%s`", scc_str_as_cstr(¯o->name));
|
||||
@@ -142,7 +142,7 @@ static int hash_cmp(const void *key1, const void *key2) {
|
||||
}
|
||||
|
||||
void scc_pproc_marco_table_init(scc_pproc_macro_table_t *macros) {
|
||||
Assert(macros != null);
|
||||
Assert(macros != nullptr);
|
||||
scc_hashtable_init(¯os->table, hash_func, hash_cmp);
|
||||
}
|
||||
|
||||
@@ -154,7 +154,7 @@ static int macro_free(const void *key, void *value, void *context) {
|
||||
}
|
||||
|
||||
void scc_pproc_macro_table_drop(scc_pproc_macro_table_t *macros) {
|
||||
Assert(macros != null);
|
||||
scc_hashtable_foreach(¯os->table, macro_free, null);
|
||||
Assert(macros != nullptr);
|
||||
scc_hashtable_foreach(¯os->table, macro_free, nullptr);
|
||||
scc_hashtable_drop(¯os->table);
|
||||
}
|
||||
|
||||
@@ -4,7 +4,7 @@
|
||||
#include <scc_pproc.h>
|
||||
|
||||
static int pproc_next_one_file(scc_pproc_t *pp, scc_lexer_tok_t *out) {
|
||||
scc_lexer_tok_ring_t *stream = null;
|
||||
scc_lexer_tok_ring_t *stream = nullptr;
|
||||
scc_lexer_tok_t tok = {0};
|
||||
int ok = 0;
|
||||
CONTINUE:
|
||||
@@ -57,7 +57,7 @@ CONTINUE:
|
||||
// maybe expanded
|
||||
scc_pproc_macro_t *macro =
|
||||
scc_pproc_macro_table_get(&pp->macro_table, &tok.lexeme);
|
||||
if (macro == null) {
|
||||
if (macro == nullptr) {
|
||||
scc_ring_next_consume(*stream, *out, ok);
|
||||
return ok;
|
||||
}
|
||||
@@ -118,7 +118,7 @@ void scc_pproc_add_builtin_macros(scc_pproc_macro_table_t *macro_table) {
|
||||
}
|
||||
|
||||
void scc_pproc_init(scc_pproc_t *pp, scc_lexer_tok_ring_t *input) {
|
||||
Assert(pp != null && input != null);
|
||||
Assert(pp != nullptr && input != nullptr);
|
||||
pp->org_ring = input;
|
||||
pp->cur_ring = pp->org_ring;
|
||||
scc_ring_init(pp->expanded_ring, 0, 0, 0);
|
||||
@@ -171,7 +171,7 @@ scc_lexer_tok_ring_t *scc_pproc_to_ring(scc_pproc_t *pp, int ring_size,
|
||||
|
||||
// 销毁预处理器
|
||||
void scc_pproc_drop(scc_pproc_t *pp) {
|
||||
if (pp == null)
|
||||
if (pp == nullptr)
|
||||
return;
|
||||
Assert(pp->cur_ring == pp->org_ring);
|
||||
scc_lexer_drop_ring(pp->org_ring);
|
||||
|
||||
@@ -134,5 +134,5 @@ TEST_LIST = {
|
||||
TEST_LIST_CASE(test_define_double_pos),
|
||||
TEST_LIST_CASE(test_define_param_pos),
|
||||
TEST_LIST_CASE(test_define_stringify_pos),
|
||||
{NULL, NULL},
|
||||
{nullptr, nullptr},
|
||||
};
|
||||
|
||||
@@ -39,7 +39,7 @@ static cbool process_input(const char *input, scc_str_t *output) {
|
||||
do { \
|
||||
scc_str_t output; \
|
||||
process_input(input, &output); \
|
||||
assert(output.data != NULL); \
|
||||
assert(output.data != nullptr); \
|
||||
TEST_CHECK(strcmp(output.data, expect) == 0); \
|
||||
TEST_MSG("Expected: %s", expect); \
|
||||
TEST_MSG("Produced: %s", output.data); \
|
||||
@@ -50,8 +50,8 @@ static cbool process_input(const char *input, scc_str_t *output) {
|
||||
do { \
|
||||
scc_str_t output; \
|
||||
process_input(input, &output); \
|
||||
assert(output.data != NULL); \
|
||||
TEST_CHECK(strstr(output.data, expect) != NULL); \
|
||||
assert(output.data != nullptr); \
|
||||
TEST_CHECK(strstr(output.data, expect) != nullptr); \
|
||||
TEST_MSG("Expected: %s", expect); \
|
||||
TEST_MSG("Produced: %s", output.data); \
|
||||
scc_str_drop(&output); \
|
||||
@@ -649,5 +649,5 @@ TEST_LIST = {
|
||||
TEST_LIST_CASE(test_real_case),
|
||||
|
||||
TEST_LIST_CASE(test_c99_docs),
|
||||
{NULL, NULL},
|
||||
{nullptr, nullptr},
|
||||
};
|
||||
|
||||
@@ -25,7 +25,7 @@ static inline sccf_sym_t *
|
||||
sccf_builder_get_symbol_unsafe(sccf_builder_t *builder, const char *name) {
|
||||
usize idx = sccf_builder_get_symbol_idx(builder, name);
|
||||
if (idx == 0) {
|
||||
return null;
|
||||
return nullptr;
|
||||
}
|
||||
return &scc_vec_at(builder->symtab, idx);
|
||||
}
|
||||
|
||||
@@ -34,12 +34,12 @@ static inline u8 *sccf_sect_header_table(u8 *base) {
|
||||
* @brief 获取指定索引的节头指针
|
||||
* @param base 文件缓冲区起始地址
|
||||
* @param idx 节索引 (0 <= idx < sect_header_num)
|
||||
* @return 指向该节头的指针, 若索引无效返回 null
|
||||
* @return 指向该节头的指针, 若索引无效返回 nullptr
|
||||
*/
|
||||
static inline sccf_sect_header_t *sccf_sect_header(u8 *base, usize idx) {
|
||||
sccf_header_t *hdr = (sccf_header_t *)base;
|
||||
if (idx >= (usize)hdr->sect_header_num)
|
||||
return null;
|
||||
return nullptr;
|
||||
u8 *table = sccf_sect_header_table(base);
|
||||
return (sccf_sect_header_t *)(table + idx * sizeof(sccf_sect_header_t));
|
||||
}
|
||||
@@ -76,11 +76,11 @@ static inline usize sccf_sect_data_offset(u8 *base, usize idx) {
|
||||
* @brief 获取指定索引的节数据起始地址
|
||||
* @param base 文件缓冲区起始地址
|
||||
* @param idx 节索引
|
||||
* @return 数据起始地址, 若索引无效返回 null
|
||||
* @return 数据起始地址, 若索引无效返回 nullptr
|
||||
*/
|
||||
static inline u8 *sccf_sect_data(u8 *base, usize idx) {
|
||||
usize off = sccf_sect_data_offset(base, idx);
|
||||
return (off == 0) ? null : base + off;
|
||||
return (off == 0) ? nullptr : base + off;
|
||||
}
|
||||
|
||||
/** @} */
|
||||
|
||||
@@ -14,11 +14,11 @@ void sccf_builder_init(sccf_builder_t *builder) {
|
||||
scc_vec_init(builder->relocs);
|
||||
scc_vec_init(builder->symtab);
|
||||
|
||||
builder->entry_symbol_name = null;
|
||||
builder->entry_symbol_name = nullptr;
|
||||
|
||||
///< Push null
|
||||
///< Push nullptr
|
||||
scc_vec_push(builder->strtab, (char)'\0');
|
||||
///< Push null
|
||||
///< Push nullptr
|
||||
scc_vec_push(builder->symtab, (sccf_sym_t){0});
|
||||
}
|
||||
|
||||
@@ -69,12 +69,12 @@ void sccf_builder_add_section(sccf_builder_t *builder,
|
||||
}
|
||||
|
||||
const sccf_t *sccf_builder_to_sccf(sccf_builder_t *builder) {
|
||||
if (builder->entry_symbol_name == null) {
|
||||
if (builder->entry_symbol_name == nullptr) {
|
||||
builder->sccf.header.entry_point = 0;
|
||||
} else {
|
||||
sccf_sym_t *sym =
|
||||
sccf_builder_get_symbol_unsafe(builder, builder->entry_symbol_name);
|
||||
if (sym == null || sym->sccf_sect_type != SCCF_SECT_CODE) {
|
||||
if (sym == nullptr || sym->sccf_sect_type != SCCF_SECT_CODE) {
|
||||
LOG_ERROR("entry symbol %s not found");
|
||||
builder->sccf.header.entry_point = 0;
|
||||
} else {
|
||||
@@ -125,14 +125,14 @@ const sccf_t *sccf_builder_to_sccf(sccf_builder_t *builder) {
|
||||
}
|
||||
|
||||
void sccf_builder_to_buffer(sccf_builder_t *builder, sccf_buffer_t *buffer) {
|
||||
Assert(builder != null && buffer != null);
|
||||
Assert(builder != nullptr && buffer != nullptr);
|
||||
sccf_write(sccf_builder_to_sccf(builder), buffer);
|
||||
}
|
||||
|
||||
void sccf_builder_to_file(sccf_builder_t *builder, const char *file_path) {
|
||||
Assert(builder != null && file_path != null);
|
||||
Assert(builder != nullptr && file_path != nullptr);
|
||||
scc_file_t fp = scc_fopen(file_path, SCC_FILE_WRITE);
|
||||
if (fp == null) {
|
||||
if (fp == nullptr) {
|
||||
LOG_ERROR("file can't open %s", file_path);
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -12,7 +12,7 @@ int main(int argc, char **argv) {
|
||||
return 1;
|
||||
}
|
||||
ring = scc_sstream_ref_ring(&stream);
|
||||
Assert(ring != null);
|
||||
Assert(ring != nullptr);
|
||||
|
||||
printf("Reading file: %s\n", filename);
|
||||
|
||||
|
||||
@@ -14,8 +14,8 @@ extern logger_t __scc_usr_log;
|
||||
"%s:%zu:%zu: ", (pos).name, (pos).line, (pos).col); \
|
||||
scc_snprintf(_full_msg + _n, sizeof(_full_msg) - _n, fmt, \
|
||||
##__VA_ARGS__); \
|
||||
__scc_usr_log.handler(&__scc_usr_log, level, null, 0, null, "%s", \
|
||||
_full_msg); \
|
||||
__scc_usr_log.handler(&__scc_usr_log, level, nullptr, 0, nullptr, \
|
||||
"%s", _full_msg); \
|
||||
} while (0)
|
||||
|
||||
#define SCC_DEBUG(pos, fmt, ...) \
|
||||
|
||||
@@ -7,7 +7,7 @@ static int user_log_handler(logger_t *module, log_level_t level,
|
||||
/* clang-format off */
|
||||
(void) module, (void)file, (void)line, (void)func; // 不再使用
|
||||
|
||||
const char *level_str = null;
|
||||
const char *level_str = nullptr;
|
||||
switch (level) {
|
||||
case LOG_LEVEL_DEBUG: level_str = "DEBUG"; break;
|
||||
case LOG_LEVEL_INFO: level_str = "INFO "; break;
|
||||
|
||||
@@ -67,7 +67,7 @@ static int sstream_scan_at(scc_sstream_t *stream, scc_pos_t scan_pos,
|
||||
|
||||
// 环形缓冲区填充回调(通过 userdata 获取流对象)
|
||||
static cbool fill_func(scc_sstream_char_t *out, void *userdata) {
|
||||
Assert(out != null && userdata != null);
|
||||
Assert(out != nullptr && userdata != nullptr);
|
||||
scc_sstream_t *stream = (scc_sstream_t *)userdata;
|
||||
if (stream->fill_pos.offset >= stream->len)
|
||||
return false; // 已到文件尾
|
||||
@@ -81,9 +81,9 @@ static cbool fill_func(scc_sstream_char_t *out, void *userdata) {
|
||||
}
|
||||
|
||||
int scc_sstream_init(scc_sstream_t *stream, const char *fname, int ring_size) {
|
||||
Assert(stream != null && fname != null);
|
||||
Assert(stream != nullptr && fname != nullptr);
|
||||
scc_file_t file = scc_fopen(fname, SCC_FILE_READ);
|
||||
if (file == null) {
|
||||
if (file == nullptr) {
|
||||
LOG_ERROR("Failed to open file: %s", fname);
|
||||
return 1;
|
||||
}
|
||||
@@ -123,13 +123,13 @@ int scc_sstream_init_by_buffer(scc_sstream_t *stream, const char *buffer,
|
||||
}
|
||||
|
||||
scc_sstream_ring_t *scc_sstream_to_ring(scc_sstream_t *stream) {
|
||||
Assert(stream != null);
|
||||
Assert(stream != nullptr);
|
||||
stream->used++;
|
||||
return &stream->ring;
|
||||
}
|
||||
|
||||
void scc_sstream_drop_ring(scc_sstream_ring_t *ring) {
|
||||
Assert(ring != null && ring->userdata != null);
|
||||
Assert(ring != nullptr && ring->userdata != nullptr);
|
||||
scc_sstream_t *stream = (scc_sstream_t *)ring->userdata;
|
||||
if (stream->used > 0) {
|
||||
stream->used--;
|
||||
@@ -139,14 +139,14 @@ void scc_sstream_drop_ring(scc_sstream_ring_t *ring) {
|
||||
}
|
||||
|
||||
void scc_sstream_drop(scc_sstream_t *stream) {
|
||||
Assert(stream != null);
|
||||
Assert(stream != nullptr);
|
||||
if (stream->used) {
|
||||
LOG_FATAL("drop sstream must be drop ring before ref [%d]",
|
||||
stream->used);
|
||||
}
|
||||
if (stream->src && stream->owned_src) {
|
||||
scc_free((void *)stream->src);
|
||||
stream->src = null;
|
||||
stream->src = nullptr;
|
||||
}
|
||||
scc_ring_free(stream->ring);
|
||||
}
|
||||
|
||||
@@ -384,7 +384,7 @@ typedef struct _IMAGE_SECTION_HEADER {
|
||||
// 导入表相关
|
||||
typedef struct _IMAGE_IMPORT_DESCRIPTOR {
|
||||
union {
|
||||
DWORD Characteristics; // 0 for terminating null import descriptor
|
||||
DWORD Characteristics; // 0 for terminating nullptr import descriptor
|
||||
DWORD OriginalFirstThunk; // RVA to original unbound IAT
|
||||
// (PIMAGE_THUNK_DATA)
|
||||
} DUMMYUNIONNAME;
|
||||
@@ -680,7 +680,7 @@ typedef IMAGE_SYMBOL UNALIGNED *PIMAGE_SYMBOL;
|
||||
|
||||
// 符号存储类
|
||||
#define IMAGE_SYM_CLASS_END_OF_FUNCTION (BYTE) - 1
|
||||
#define IMAGE_SYM_CLASS_NULL 0x0000
|
||||
#define IMAGE_SYM_CLASS_nullptr 0x0000
|
||||
#define IMAGE_SYM_CLASS_AUTOMATIC 0x0001
|
||||
#define IMAGE_SYM_CLASS_EXTERNAL 0x0002
|
||||
#define IMAGE_SYM_CLASS_STATIC 0x0003
|
||||
|
||||
@@ -355,7 +355,7 @@ scc_pe_section_range scc_pe_reserve_section_header(scc_pe_builder_t *builder,
|
||||
void scc_pe_write_section(scc_pe_builder_t *builder,
|
||||
scc_pe_section_range *range, u8 *data,
|
||||
usize data_size) {
|
||||
if (range == null || data == null || data_size == 0) {
|
||||
if (range == nullptr || data == nullptr || data_size == 0) {
|
||||
return;
|
||||
}
|
||||
padding_util(builder, range->file_offset);
|
||||
|
||||
@@ -156,11 +156,12 @@ scc_pe_buffer_t scc_pe_construct_idata(scc_pe_idata_builder_t *builder,
|
||||
&scc_vec_at(lookup_table, 0), table_size);
|
||||
}
|
||||
|
||||
// 添加NULL终止的目录项
|
||||
IMAGE_IMPORT_DESCRIPTOR null_entry = image_import_descriptor_init(0, 0, 0);
|
||||
// 添加nullptr终止的目录项
|
||||
IMAGE_IMPORT_DESCRIPTOR nullptr_entry =
|
||||
image_import_descriptor_init(0, 0, 0);
|
||||
scc_memcpy(&scc_vec_at(builder->buffer,
|
||||
import_file_count * sizeof(IMAGE_IMPORT_DESCRIPTOR)),
|
||||
&null_entry, sizeof(IMAGE_IMPORT_DESCRIPTOR));
|
||||
&nullptr_entry, sizeof(IMAGE_IMPORT_DESCRIPTOR));
|
||||
|
||||
// 填充Hint/Name表
|
||||
scc_memcpy(&scc_vec_at(builder->buffer, hnt_offset),
|
||||
|
||||
@@ -22,14 +22,14 @@ static void load_from_def(pe_idata_lib_ctx_t *ctx, const char *file_path,
|
||||
scc_str_append_cstr(&fpath, ".def", 4);
|
||||
const char *fname = scc_str_as_cstr(&fpath);
|
||||
scc_file_t fp = scc_fopen(fname, SCC_FILE_READ);
|
||||
if (fp == null) {
|
||||
if (fp == nullptr) {
|
||||
LOG_ERROR("load_from_def file read error: %s", fname);
|
||||
return;
|
||||
}
|
||||
|
||||
usize fsize = scc_fsize(fp);
|
||||
char *buffer = scc_malloc(fsize);
|
||||
Assert(buffer != null);
|
||||
Assert(buffer != nullptr);
|
||||
|
||||
usize read_size = scc_fread(fp, buffer, fsize);
|
||||
Assert(read_size == fsize);
|
||||
@@ -71,11 +71,11 @@ static void pe_idata_lib_init(pe_idata_lib_ctx_t *ctx, const char *find_path) {
|
||||
|
||||
static cbool pe_idata_get(pe_idata_lib_ctx_t *ctx, const char *name) {
|
||||
const char *lib_name = scc_hashtable_get(&ctx->str2libsym, name);
|
||||
if (lib_name == null) {
|
||||
if (lib_name == nullptr) {
|
||||
return false;
|
||||
}
|
||||
|
||||
scc_pe_idata_lib_t *lib = null;
|
||||
scc_pe_idata_lib_t *lib = nullptr;
|
||||
scc_vec_foreach(ctx->idata_libs, i) {
|
||||
scc_pe_idata_lib_t *idata_lib = &scc_vec_at(ctx->idata_libs, i);
|
||||
if (scc_strcmp(lib_name, idata_lib->name) == 0) {
|
||||
@@ -83,7 +83,7 @@ static cbool pe_idata_get(pe_idata_lib_ctx_t *ctx, const char *name) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (lib == null) {
|
||||
if (lib == nullptr) {
|
||||
scc_pe_idata_lib_t new_lib;
|
||||
new_lib.name = lib_name;
|
||||
scc_vec_init(new_lib.symbol_names);
|
||||
@@ -104,8 +104,8 @@ void sccf2pe(scc_pe_builder_t *builder, const sccf_t *sccf) {
|
||||
sccf_sym_vec_t symtab;
|
||||
scc_vec_init(symtab);
|
||||
|
||||
sccf_sect_data_t *code_data = null;
|
||||
sccf_sect_data_t *data_data = null;
|
||||
sccf_sect_data_t *code_data = nullptr;
|
||||
sccf_sect_data_t *data_data = nullptr;
|
||||
int num_of_section = 1;
|
||||
scc_vec_foreach(sccf->sect_headers, i) {
|
||||
sccf_sect_header_t *sect_header = &scc_vec_at(sccf->sect_headers, i);
|
||||
@@ -221,18 +221,18 @@ void sccf2pe(scc_pe_builder_t *builder, const sccf_t *sccf) {
|
||||
TODO();
|
||||
}
|
||||
rva -= code_range.virual_address + reloc->offset + reloc->addend;
|
||||
Assert(code_data != null);
|
||||
Assert(code_data != nullptr);
|
||||
// FIXME 需要确保宿主机与目标机器大小端一致
|
||||
*(u32 *)(scc_vec_unsafe_get_data(*code_data) + reloc->offset) = rva;
|
||||
}
|
||||
|
||||
scc_pe_write_header(builder, &config);
|
||||
if (code_data != null) {
|
||||
if (code_data != nullptr) {
|
||||
scc_pe_write_section(builder, &code_range,
|
||||
(u8 *)scc_vec_unsafe_get_data(*code_data),
|
||||
scc_vec_size(*code_data));
|
||||
}
|
||||
if (data_data != null) {
|
||||
if (data_data != nullptr) {
|
||||
scc_pe_write_section(builder, &data_range,
|
||||
(u8 *)scc_vec_unsafe_get_data(*data_data),
|
||||
scc_vec_size(*data_data));
|
||||
|
||||
@@ -92,7 +92,7 @@ void scc_tree_dump_append_fmt(scc_tree_dump_t *td, const char *fmt, ...) {
|
||||
// 计算所需长度
|
||||
va_list args_copy;
|
||||
va_copy(args_copy, args);
|
||||
usize len = scc_vsnprintf(null, 0, fmt, args_copy);
|
||||
usize len = scc_vsnprintf(nullptr, 0, fmt, args_copy);
|
||||
va_end(args_copy);
|
||||
if (len == 0) {
|
||||
va_end(args);
|
||||
@@ -105,7 +105,7 @@ void scc_tree_dump_append_fmt(scc_tree_dump_t *td, const char *fmt, ...) {
|
||||
new_cap = new_cap ? new_cap * 2 : 16;
|
||||
}
|
||||
char *new_data = (char *)scc_realloc(td->buf.data, new_cap);
|
||||
Assert(new_data != null);
|
||||
Assert(new_data != nullptr);
|
||||
td->buf.data = new_data;
|
||||
td->buf.cap = new_cap;
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user