- 实现了核心寄存器分配接口 scc_reg_alloc.h - 添加 x86_64 架构特定的寄存器分配实现 - 实现基础的虚拟寄存器到物理寄存器分配逻辑 - 支持栈槽分配和重载/存储指令生成 fix(argparse): 修复帮助信息打印中的枚举类型显示 - 将固定大小缓冲区改为动态字符串处理 - 正确显示枚举类型的选项值和可选值列表 - 使用 | 分隔符展示多个可选值 refactor(main): 调整编译流程中的 pass 阶段支持 - 更新配置文件中各编译阶段的名称定义 - 添加对寄存器分配、帧布局等中间表示 pass 的支持 - 重构主流程以支持不同 MIR 阶段的代码输出
267 lines
8.9 KiB
C
267 lines
8.9 KiB
C
#include <argparse.h>
|
||
|
||
// 帮助信息处理函数
|
||
enum {
|
||
ARGPARSE_USAGE,
|
||
ARGPARSE_OPTION,
|
||
ARGPARSE_COMMAND,
|
||
ARGPARSE_ARGUMENT,
|
||
|
||
ARGPARSE_SHOW_ARG,
|
||
ARGPARSE_SHOW_OPT,
|
||
ARGPARSE_SHOW_CMD,
|
||
ARGPARSE_SHOW_HELP_MSG,
|
||
|
||
ARGPRASE_USING_HELP_HINT,
|
||
ARGPARSE_UNKNOWN_ARGUMENT,
|
||
ARGPARSE_INVALID_VALUE_FOR_OPTION,
|
||
ARGPARSE_OPTION_MISSING_VALUE,
|
||
ARGPARSE_DID_YOU_MEAN,
|
||
};
|
||
|
||
static const char *fmt_en[] = {
|
||
[ARGPARSE_USAGE] = "Usage: %s",
|
||
[ARGPARSE_OPTION] = " [Options]",
|
||
[ARGPARSE_COMMAND] = " [Commands]",
|
||
|
||
[ARGPARSE_SHOW_ARG] = "Arguments:\n",
|
||
[ARGPARSE_SHOW_OPT] = "Options:\n",
|
||
[ARGPARSE_SHOW_CMD] = "Commands:\n",
|
||
[ARGPARSE_SHOW_HELP_MSG] = "Show this help message and exit",
|
||
|
||
[ARGPRASE_USING_HELP_HINT] =
|
||
"Using '-h' or '--help' to get more information\n",
|
||
[ARGPARSE_UNKNOWN_ARGUMENT] = "Unknown argument '%s'\n",
|
||
[ARGPARSE_INVALID_VALUE_FOR_OPTION] = "Invalid value for option '%s'\n",
|
||
[ARGPARSE_OPTION_MISSING_VALUE] = "Option '%s' missing value\n",
|
||
[ARGPARSE_DID_YOU_MEAN] = "Did you mean: '%s'?\n",
|
||
};
|
||
|
||
static const char *fmt_zh[] = {
|
||
[ARGPARSE_USAGE] = "用法: %s",
|
||
[ARGPARSE_OPTION] = " [选项]",
|
||
[ARGPARSE_COMMAND] = " [命令]",
|
||
|
||
[ARGPARSE_SHOW_ARG] = "参数:\n",
|
||
[ARGPARSE_SHOW_OPT] = "选项:\n",
|
||
[ARGPARSE_SHOW_CMD] = "命令:\n",
|
||
[ARGPARSE_SHOW_HELP_MSG] = "显示帮助信息并退出",
|
||
|
||
[ARGPRASE_USING_HELP_HINT] = "使用 '-h' 或者 '--help' 获取更多信息\n",
|
||
[ARGPARSE_UNKNOWN_ARGUMENT] = "未知的参数 '%s'\n",
|
||
[ARGPARSE_INVALID_VALUE_FOR_OPTION] = "无效的选项值 '%s'\n",
|
||
[ARGPARSE_OPTION_MISSING_VALUE] = "选项 '%s' 缺少值\n",
|
||
[ARGPARSE_DID_YOU_MEAN] = "您是不是想要输入: '%s'?\n",
|
||
};
|
||
|
||
/**
|
||
* @brief 计算两个字符串的编辑距离(Levenshtein距离)
|
||
* @param s1 字符串1(非空,以'\0'结尾)
|
||
* @param s2 字符串2(非空,以'\0'结尾)
|
||
* @return 编辑距离,内存分配失败返回 -1
|
||
*/
|
||
static int scc_levenshtein(const char *s1, const char *s2) {
|
||
usize len1 = scc_strlen(s1);
|
||
usize len2 = scc_strlen(s2);
|
||
|
||
// 保证 len1 >= len2 以减少内存占用
|
||
if (len1 < len2) {
|
||
const char *tmp = s1;
|
||
s1 = s2;
|
||
s2 = tmp;
|
||
usize tlen = len1;
|
||
len1 = len2;
|
||
len2 = tlen;
|
||
}
|
||
|
||
// 分配滚动数组(只需 len2+1 个 int)
|
||
int *dp = (int *)scc_malloc(sizeof(int) * (len2 + 1));
|
||
if (!dp)
|
||
return -1;
|
||
|
||
// 初始化第0行
|
||
for (usize j = 0; j <= len2; ++j)
|
||
dp[j] = (int)j;
|
||
|
||
for (usize i = 1; i <= len1; ++i) {
|
||
int prev = dp[0];
|
||
dp[0] = (int)i;
|
||
for (usize j = 1; j <= len2; ++j) {
|
||
int temp = dp[j];
|
||
int cost = (s1[i - 1] == s2[j - 1]) ? 0 : 1;
|
||
dp[j] = scc_min(scc_min(dp[j] + 1, dp[j - 1] + 1), prev + cost);
|
||
prev = temp;
|
||
}
|
||
}
|
||
|
||
int dist = dp[len2];
|
||
scc_free(dp);
|
||
return dist;
|
||
}
|
||
|
||
static void print_usage(scc_argparse_t *parser, scc_argparse_cmd_t *cmd) {
|
||
const char **lines =
|
||
(parser->lang == SCC_ARGPARSE_LANG_ZH) ? fmt_zh : fmt_en;
|
||
scc_printf(lines[ARGPARSE_USAGE],
|
||
cmd->name ? cmd->name : parser->prog_name);
|
||
if (scc_vec_size(cmd->opts) > 0)
|
||
scc_printf(lines[ARGPARSE_OPTION]);
|
||
scc_vec_foreach(cmd->args, i) {
|
||
scc_argparse_arg_t *arg = &scc_vec_at(cmd->args, i);
|
||
scc_printf(arg->spec.flag_required ? " <%s>" : " [%s]", arg->name);
|
||
}
|
||
if (scc_vec_size(cmd->subcmds) > 0)
|
||
scc_printf(lines[ARGPARSE_COMMAND]);
|
||
scc_printf("\n\n");
|
||
}
|
||
|
||
void scc_argparse_print_help(scc_argparse_t *parser, scc_argparse_cmd_t *cmd) {
|
||
const char **lines =
|
||
(parser->lang == SCC_ARGPARSE_LANG_ZH) ? fmt_zh : fmt_en;
|
||
|
||
print_usage(parser, cmd);
|
||
|
||
if (cmd->description)
|
||
scc_printf("%s\n\n", cmd->description);
|
||
|
||
if (scc_vec_size(cmd->args) > 0) {
|
||
scc_printf(lines[ARGPARSE_SHOW_ARG]);
|
||
scc_vec_foreach(cmd->args, i) {
|
||
scc_argparse_arg_t *arg = &scc_vec_at(cmd->args, i);
|
||
scc_printf(" %-20s %s", arg->name,
|
||
arg->description ? arg->description : "");
|
||
// if (!arg->spec.required && arg->spec.flags.has_default)
|
||
// scc_printf(" (default: %s)", arg->spec.default_value);
|
||
scc_printf("\n");
|
||
}
|
||
scc_printf("\n");
|
||
}
|
||
|
||
if (scc_vec_size(cmd->opts) > 0) {
|
||
scc_printf(lines[ARGPARSE_SHOW_OPT]);
|
||
scc_vec_foreach(cmd->opts, i) {
|
||
scc_argparse_opt_t *opt = &scc_vec_at(cmd->opts, i);
|
||
if (opt->spec.flag_hidden)
|
||
continue;
|
||
if (opt->short_name == 'h')
|
||
opt->description = lines[ARGPARSE_SHOW_HELP_MSG];
|
||
scc_str_t buf;
|
||
scc_str_init(&buf);
|
||
int pos = 0;
|
||
if (opt->short_name) {
|
||
scc_str_append_ch(&buf, '-');
|
||
scc_str_append_ch(&buf, opt->short_name);
|
||
if (opt->long_name) {
|
||
scc_str_append_ch(&buf, ',');
|
||
scc_str_append_ch(&buf, ' ');
|
||
}
|
||
}
|
||
if (opt->long_name) {
|
||
scc_str_append_ch(&buf, '-');
|
||
scc_str_append_ch(&buf, '-');
|
||
scc_str_append_cstr(&buf, opt->long_name,
|
||
scc_strlen(opt->long_name));
|
||
}
|
||
if (opt->spec.value_type == SCC_ARGPARSE_VAL_TYPE_ENUM) {
|
||
scc_str_append_ch(&buf, '=');
|
||
scc_str_append_ch(&buf, '<');
|
||
for (int j = 0; j < opt->spec.choices.count; j += 1) {
|
||
if (opt->spec.choices.values[j] == 0) {
|
||
continue;
|
||
}
|
||
|
||
if (j != 0) {
|
||
scc_str_append_ch(&buf, '|');
|
||
}
|
||
|
||
scc_str_append_cstr(
|
||
&buf, opt->spec.choices.values[j],
|
||
scc_strlen(opt->spec.choices.values[j]));
|
||
}
|
||
scc_str_append_ch(&buf, '>');
|
||
}
|
||
scc_printf(" %-25s %s", scc_str_as_cstr(&buf),
|
||
opt->description ? opt->description : "");
|
||
// if (opt->spec.default_value)
|
||
// scc_printf(" (default: %s)", opt->spec.default_value);
|
||
scc_printf("\n");
|
||
}
|
||
scc_printf("\n");
|
||
}
|
||
|
||
if (scc_vec_size(cmd->subcmds) > 0) {
|
||
scc_printf(lines[ARGPARSE_SHOW_CMD]);
|
||
scc_vec_foreach(cmd->subcmds, i) {
|
||
scc_argparse_cmd_t *sub = &scc_vec_at(cmd->subcmds, i);
|
||
scc_printf(" %-20s %s\n", sub->name,
|
||
sub->description ? sub->description : "");
|
||
}
|
||
scc_printf("\n");
|
||
}
|
||
if (parser->epilog)
|
||
scc_printf("%s\n", parser->epilog);
|
||
}
|
||
|
||
const char *scc_argparse_find_similar_arg(scc_argparse_cmd_t *cmd,
|
||
const char *arg) {
|
||
if (arg == nullptr || cmd == nullptr) {
|
||
return nullptr;
|
||
}
|
||
if (arg[0] == '-' && arg[1] == '-' && arg[2] != '\0') {
|
||
// opt arg
|
||
scc_vec_foreach(cmd->opts, i) {
|
||
if (scc_levenshtein(arg + 2, scc_vec_at(cmd->opts, i).long_name) <=
|
||
2) {
|
||
return scc_vec_at(cmd->opts, i).long_name;
|
||
}
|
||
}
|
||
} else {
|
||
// subcmd arg
|
||
scc_vec_foreach(cmd->subcmds, i) {
|
||
if (scc_levenshtein(arg, scc_vec_at(cmd->subcmds, i).name) <= 2) {
|
||
return scc_vec_at(cmd->subcmds, i).name;
|
||
}
|
||
}
|
||
}
|
||
return 0;
|
||
}
|
||
|
||
void scc_argparse_print_error(scc_argparse_context_t *ctx,
|
||
scc_argparse_t *parser, scc_argparse_err_t err) {
|
||
const char **lines =
|
||
(parser->lang == SCC_ARGPARSE_LANG_ZH) ? fmt_zh : fmt_en;
|
||
switch (err) {
|
||
case SCC_ARGPARSE_ERR_INVALID_ARG:
|
||
case SCC_ARGPARSE_ERR_INVALID_VALUE:
|
||
scc_printf(lines[ARGPARSE_INVALID_VALUE_FOR_OPTION], ctx->err_ctx);
|
||
break;
|
||
case SCC_ARGPARSE_ERR_MISSING_ARG:
|
||
case SCC_ARGPARSE_ERR_MISSING_VALUE:
|
||
scc_printf(lines[ARGPARSE_OPTION_MISSING_VALUE], ctx->err_ctx);
|
||
break;
|
||
case SCC_ARGPARSE_ERR_UNKNOWN_ARG:
|
||
case SCC_ARGPARSE_ERR_UNKNOWN_VALUE:
|
||
scc_printf(lines[ARGPARSE_UNKNOWN_ARGUMENT], ctx->result.raw_arg);
|
||
const char *similar_arg = scc_argparse_find_similar_arg(
|
||
ctx->current_cmd, ctx->result.raw_arg);
|
||
if (similar_arg != 0) {
|
||
scc_printf(lines[ARGPARSE_DID_YOU_MEAN], similar_arg);
|
||
}
|
||
break;
|
||
// FACK ERROR
|
||
case SCC_ARGPARSE_ERR_PNT_DEFAULT:
|
||
return;
|
||
default:
|
||
scc_printf("Unknown error: %d\n", err);
|
||
break;
|
||
}
|
||
if (parser->need_help) {
|
||
scc_printf(lines[ARGPRASE_USING_HELP_HINT]);
|
||
}
|
||
if (parser->need_error_add_help) {
|
||
scc_argparse_print_help(parser, ctx->current_cmd);
|
||
} else if (parser->need_error_add_usage) {
|
||
print_usage(parser, ctx->current_cmd);
|
||
}
|
||
}
|