Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
26 changes: 22 additions & 4 deletions src/compile/c_gen.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -93,7 +93,19 @@ void CGen::UniquifyFuncCNames() {
if (func.get() == real_init) {
continue;
}
std::string base = func->unique_c_name.empty() ? "flua_fn" : func->unique_c_name;
std::string base;
if (func->unique_c_name.empty()) {
base = "flua_fn";
} else if (func->parent == nullptr) {
// 顶层用户函数统一加 flua_fn_ 前缀:
// 1) 规避 C 宿主对 main 的入口签名校验(Clang 报 first parameter of 'main');
// 2) 规避与 libc/头文件同名符号(sin/printf/...)的重定义冲突;
// 3) 顺带规避其余 C 保留/外部标识符。
// 嵌套函数在 ResolveScopes 中已取得 __fl_func_N 形式的唯一名,无需再加前缀。
base = std::string("flua_fn_") + func->unique_c_name;
} else {
base = func->unique_c_name;
}
if (base == kInitFunctionName) {
base = std::string("flua_id_") + kInitFunctionName;
}
Expand Down Expand Up @@ -2096,7 +2108,9 @@ void CGen::CompileStmtForIn(const SyntaxTreeInterfacePtr &stmt) {
Out() << GenTab() << iter_s << " = FlUnboxMulti(" << e1 << ", 0);\n";
Out() << GenTab() << iter_var << " = FlUnboxMulti(" << e2 << ", 0);\n";
for (size_t i = 3; i < exps.size(); ++i) {
Out() << GenTab() << "(void)(" << CompileExp(exps[i], i + 1 == exps.size()) << ");\n";
// 同 CompileCallArgs:CompileExp 可能先发语句宏,必须先求值再拼接输出。
const std::string discarded_exp = CompileExp(exps[i], i + 1 == exps.size());
Out() << GenTab() << "(void)(" << discarded_exp << ");\n";
}
}

Expand Down Expand Up @@ -4464,10 +4478,14 @@ void CGen::CompileCallArgs(const std::shared_ptr<SyntaxTreeArgs> &args_ptr, Args
for (size_t i = 0; i < raw_args.size() - 1; ++i) {
compiled_args.push_back(CompileExp(raw_args[i]));
}
// Compile the last function call/vararg into a temporary variable
// Compile the last function call/vararg into a temporary variable.
// 注意:必须先求值 CompileExp(它会把慢路径语句宏/if-else 直接写入输出流),
// 再输出赋值语句,否则「左值前缀」与「结果表达式」会被中途发出的语句撕开,
// 生成 x = do{...}while(0); 这类非法 C(见 FAKELUA_JIT_BUG_REPORT 缺陷 2)。
expansion_tmp = std::format("flua_call_res_{}", tmp_var_counter_++);
func_temp_decls_ << " CVar " << expansion_tmp << ";\n";
Out() << GenTab() << expansion_tmp << " = " << CompileExp(raw_args.back(), true) << ";\n";
const std::string last_expansion_arg = CompileExp(raw_args.back(), true);
Out() << GenTab() << expansion_tmp << " = " << last_expansion_arg << ";\n";
expansion_start_idx = raw_args.size() - 1;
} else {
for (const auto &exp: raw_args) {
Expand Down
5 changes: 4 additions & 1 deletion src/compile/c_runtime_header.h
Original file line number Diff line number Diff line change
Expand Up @@ -341,7 +341,10 @@ extern CVar FakeluaInterpCall(State *state, VarClosure *cl, int arg_num, const C

#define kMaxFunctionInputParams 32

static inline CVar FlMakeClosure(State *state, void *func_ptr, int upvalue_count, int expected_arg_count, bool is_vararg, ...) {
// 注意:is_vararg 必须声明为 int 而非 bool。C17 7.16.1.4 规定 va_start 的最后一个
// 具名形参若类型会受默认实参提升影响(bool/_Bool 会被提升为 int),行为未定义。
// 调用处传入的 true/false 会隐式转换为 int。
static inline CVar FlMakeClosure(State *state, void *func_ptr, int upvalue_count, int expected_arg_count, int is_vararg, ...) {
VarClosure *cl = (VarClosure *)FakeluaAlloc(state, sizeof(VarClosure) + upvalue_count * sizeof(CVar *), !__fakelua_init_flag__);
cl->func_ptr = func_ptr;
cl->upvalue_count = upvalue_count;
Expand Down
5 changes: 5 additions & 0 deletions src/compile/compile_common.h
Original file line number Diff line number Diff line change
Expand Up @@ -294,6 +294,11 @@ struct ParseResult {
struct AnalysisResult {
// 函数名 -> 最大返回值数量(-1 代表动态,例如以函数调用结尾)
std::unordered_map<std::string, int> function_max_returns;
// 函数名 -> 有效返回值数量:在 function_max_returns 基础上把「return f()」尾调用
// 沿被调函数链做定点求解(含递归自调用锚点),例如 f()=return g()、g()=return 1
// 会解析为 1。-1 表示无法静态确定(未知被调/vararg/无锚点递归环)。
// 仅供数学参数特化的资格判定使用,不影响既有代码生成路径。
std::unordered_map<std::string, int> function_effective_returns;
// 语法分析出的所有函数调用表达式节点集合,供 CGen 直接查询
std::unordered_set<const SyntaxTreeInterface *> function_call_exps;
// 语法分析出的所有函数调用到其被调用者名字的映射,供 CGen 直接查询
Expand Down
2 changes: 1 addition & 1 deletion src/compile/compiler.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -82,7 +82,7 @@ ParseResult Compiler::Compile(MyFlexer &f, const CompileConfig &cfg) {
// 5. 类型推导(同时识别数学参数)
LOG_DEBUG(s_, "engine", "step 5: type inference");
TypeInferencer inferencer(s_);
InferResult ir = inferencer.InferTypes(pr, cfg);
InferResult ir = inferencer.InferTypes(pr, ar, cfg);

// 6. 转译为C(TCC/GCC 需要;仅解释器时跳过)
const bool need_c = !cfg.disable_jit[JIT_TCC] || !cfg.disable_jit[JIT_GCC] || cfg.record_c_code;
Expand Down
117 changes: 114 additions & 3 deletions src/compile/semantic_analysis.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -89,6 +89,22 @@ void SemanticAnalysis::AnalyzeGlobalConstNames(const SyntaxTreeInterfacePtr &chu
void SemanticAnalysis::AnalyzeFunctionReturnCounts(const SyntaxTreeInterfacePtr &chunk, AnalysisResult &ar) {
DEBUG_ASSERT(chunk->Type() == SyntaxTreeType::Block);
const auto block = std::dynamic_pointer_cast<SyntaxTreeBlock>(chunk);

// 每个文件级函数的返回值明细,用于在 function_max_returns 之上做
// 「尾调用链有效返回数」定点求解(仅供数学参数特化资格判定)。
struct FuncReturnInfo {
// 是否存在不以尾调用/vararg 结尾的 return(含裸 return),其最大显式返回数
bool has_concrete = false;
int concrete_max = 0;
// 存在 return ...(vararg 尾展开)
bool has_vararg_tail = false;
// 存在尾调用指向无法解析的被调(原生函数/方法/外部符号):返回数不可知
bool has_unknown_tail = false;
// 尾调用指向的本文件级函数名
std::vector<std::string> tail_callees;
};
std::unordered_map<std::string, FuncReturnInfo> infos;

for (const auto &stmt: block->Stmts()) {
std::string name;
SyntaxTreeInterfacePtr funcbody;
Expand All @@ -114,22 +130,117 @@ void SemanticAnalysis::AnalyzeFunctionReturnCounts(const SyntaxTreeInterfacePtr
CollectReturnsForBlock(func_block, returns);

int max_returns = 0;
auto &info = infos[name];
for (const auto &ret_node: returns) {
const auto ret = std::dynamic_pointer_cast<SyntaxTreeReturn>(ret_node);
const auto el = std::dynamic_pointer_cast<SyntaxTreeExplist>(ret->Explist());
if (!el || el->Exps().empty()) {
// return count is 0
info.has_concrete = true;
continue;
}
const auto &ret_exps = el->Exps();
int count = static_cast<int>(ret_exps.size());
if (IsFunctionCallExp(ret_exps.back())) {
max_returns = -1;// dynamic
if (count == 1) {
// 唯一返回表达式是尾调用:记录被调函数名用于定点求解
const std::string callee = GetCalleeName(ret_exps.back());
if (callee.empty()) {
info.has_unknown_tail = true;
} else {
info.tail_callees.push_back(callee);
}
} else {
// 多返回值 return 且末位是调用:显式部分贡献确定数量,
// 尾调用部分另按被调链传播
info.has_concrete = true;
info.concrete_max = std::max(info.concrete_max, count);
const std::string callee = GetCalleeName(ret_exps.back());
if (callee.empty()) {
info.has_unknown_tail = true;
} else {
info.tail_callees.push_back(callee);
}
}
} else {
int count = static_cast<int>(el->Exps().size());
if (IsFunctionCallExp(el->Exps().back())) {
max_returns = -1;// dynamic
if (IsVarargExp(ret_exps.back()) && count == 1) {
// return ...:尾 vararg 展开,返回数随调用者变化
info.has_vararg_tail = true;
max_returns = -1;
} else if (max_returns >= 0) {
max_returns = std::max(max_returns, count);
}
info.has_concrete = true;
info.concrete_max = std::max(info.concrete_max, count);
}
}
ar.function_max_returns[name] = max_returns;
}

// 尾调用被调若不是本文件级函数(外部 chunk 符号),返回数同样不可知,按 tainted 处理。
for (auto &[name, info]: infos) {
for (const auto &callee: info.tail_callees) {
if (!infos.contains(callee)) {
info.has_unknown_tail = true;
break;
}
}
}

// 定点求解有效返回数,内部使用双状态:
// kTainted(-2):永久不可知(vararg 尾展开 / 未知或外部被调 / 被调链污染);
// kUnknown(-1):暂未解析(被调链尚未收敛,无 concrete 锚点的递归环停留于此);
// >=0:当前确定的最大返回数。
// 初值:直接 tainted 标记者 → kTainted;存在确定 return(含裸 return)→ concrete_max;
// 仅有尾调用 return → kUnknown 等待被调链解析。
// 迭代:边到 kTainted → 自身 kTainted(动态返回路径会污染所有上游);
// 边到 >=0 → 取 max;边到 kUnknown → 本轮等待。
// 递归自调用(如 fact 有 return 1 基线)由 concrete 锚点稳定为 1。
constexpr int kUnknown = -1;
constexpr int kTainted = -2;
for (const auto &[name, info]: infos) {
if (info.has_vararg_tail || info.has_unknown_tail) {
ar.function_effective_returns[name] = kTainted;
} else if (info.has_concrete) {
ar.function_effective_returns[name] = info.concrete_max;
} else {
ar.function_effective_returns[name] = kUnknown;
}
}
for (size_t round = 0; round < infos.size() + 1; ++round) {
bool changed = false;
for (const auto &[name, info]: infos) {
int &cur = ar.function_effective_returns[name];
if (cur == kTainted) {
continue;
}
for (const auto &callee: info.tail_callees) {
const int cv = ar.function_effective_returns.at(callee);
if (cv == kTainted) {
cur = kTainted;
changed = true;
break;
}
if (cv == kUnknown) {
continue;
}
if (cur == kUnknown || cv > cur) {
cur = cv;
changed = true;
}
}
}
if (!changed) {
break;
}
}
// 对外统一输出:kTainted 与仍未解析的 kUnknown 都记为 -1(不可特化)。
for (auto &[name, v]: ar.function_effective_returns) {
if (v < 0) {
v = -1;
}
}
}

void SemanticAnalysis::CollectReturnsForBlock(const SyntaxTreeInterfacePtr &node, std::vector<SyntaxTreeInterfacePtr> &returns) {
Expand Down
Loading
Loading