Skip to content
Merged
1 change: 1 addition & 0 deletions src/compile/c_gen.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -488,6 +488,7 @@ void CGen::GenerateGlobal(const SyntaxTreeInterfacePtr &chunk) {
InferredType global_type = ir().global_const_vars.at(name);
const auto cname = CIdent(name);
const auto exp_node = std::dynamic_pointer_cast<SyntaxTreeExp>(exp);
// 文件级数值 local 是常量。再赋值在类型推断阶段就已经报错,这里一律 static const。
if (global_type == T_INT) {
if (!exp_node || exp_node->GetExpKind() == ExpKind::kNil) {
Out() << "static const int64_t " << cname << " = 0;\n";
Expand Down
14 changes: 12 additions & 2 deletions src/compile/c_runtime_header.h
Original file line number Diff line number Diff line change
Expand Up @@ -335,6 +335,10 @@ extern CVar FakeluaAllocMultiCVar(State *s, int count);
extern void FakeluaSetMultiCVarElement(CVar *multi, int idx, CVar val);
extern CVar FlEvalLoadClosure(State *state, VarClosure *cl, int arg_num, const CVar *args);
extern CVar FakeluaInterpCall(State *state, VarClosure *cl, int arg_num, const CVar *args);
// 当前执行引擎上下文(供 JIT C 代码调用闭包前后维护):push 切到 jit 并返回上一个引擎,
// pop 恢复。native 对象方法等在闭包内执行时据此登记派回本引擎的异步回调。
extern int FakeluaJitContextPush(State *s, int jit);
extern void FakeluaJitContextPop(State *s, int prev);
#ifdef __cplusplus
}
#endif
Expand Down Expand Up @@ -519,8 +523,13 @@ static inline CVar FlCallClosure(State *state, CVar cl_var, int arg_num, ...) {
#define FCARG_31 FCARG_30, arg_arr[30]
#define FCARG_32 FCARG_31, arg_arr[31]

#define FCCASE(N) \
case N: return ((CVar (*)(VarClosure * FCCVAR_##N))(addr))(cl FCARG_##N);
#define FCCASE(N) \
case N: { \
int __fl_prev_jit = FakeluaJitContextPush(state, FAKELUA_JIT_TYPE); \
CVar __fl_ret = ((CVar (*)(VarClosure * FCCVAR_##N))(addr))(cl FCARG_##N); \
FakeluaJitContextPop(state, __fl_prev_jit); \
return __fl_ret; \
}

switch (expected_arg_count) {
FCCASE(0) FCCASE(1) FCCASE(2) FCCASE(3) FCCASE(4) FCCASE(5)
Expand Down Expand Up @@ -667,6 +676,7 @@ static inline uint32_t FlHashString(const char *str, int len) {
(v).data_.t->spec_keys = (CVar *)FakeluaAlloc(_S, sizeof(CVar) * (field_count), !__fakelua_init_flag__); \
(v).data_.t->spec_vals = (CVar *)FakeluaAlloc(_S, sizeof(CVar) * (field_count), !__fakelua_init_flag__); \
(v).data_.t->spec_count = (field_count); \
assert(sizeof(SpecType) == (field_count) * sizeof(CVar)); \
} while(0)

#define FL_SPEC(SpecType, v, field) (((SpecType *)(v).data_.t->spec)->field)
Expand Down
38 changes: 37 additions & 1 deletion src/compile/type_inferencer.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,24 @@ std::string SpecStringFieldCName(const std::string &key) {
return out;
}

// 预处理生成的文件级初始化函数。它的函数体里对 local x = func() 降级出来的
// 绑定做一次赋值,不能当成用户再赋值。
bool IsFakeluaInitFunction(const std::shared_ptr<SyntaxTreeFunction> &func) {
if (!func) {
return false;
}
const auto fn = std::dynamic_pointer_cast<SyntaxTreeFuncname>(func->Funcname());
if (!fn) {
return false;
}
const auto fnl = std::dynamic_pointer_cast<SyntaxTreeFuncnamelist>(fn->FuncNameList());
if (!fnl) {
return false;
}
const auto &names = fnl->Funcnames();
return names.size() == 1 && names[0] == kInitFunctionName;
}

void UniquifySpecFieldCNames(std::vector<TableFieldInfo> &fields) {
std::unordered_set<std::string> used;
for (auto &f: fields) {
Expand Down Expand Up @@ -383,7 +401,9 @@ InferredType TypeInferencer::TypeEnvironment::MergeType(const InferredType old_t

InferResult TypeInferencer::InferTypes(const ParseResult &pr, const CompileConfig &cfg) {
LOG_DEBUG(s_, "engine", "InferTypes: start for {}", pr.file_name);
file_name_ = pr.file_name;
file_level_types_.clear();
file_level_init_exps_.clear();
InferResult ir;
EvalTypeSnapshot current_map;
TypeEnvironment env;
Expand Down Expand Up @@ -467,7 +487,12 @@ InferredType TypeInferencer::InferNode(const SyntaxTreeInterfacePtr &node, Trave
}
case SyntaxTreeType::Function: {
const auto func = std::dynamic_pointer_cast<SyntaxTreeFunction>(node);
const bool prev_init = in_init_function_;
if (IsFakeluaInitFunction(func)) {
in_init_function_ = true;
}
InferNode(func->Funcbody(), tctx);
in_init_function_ = prev_init;
return RecordType(current_map, node.get(), T_UNKNOWN);
}
case SyntaxTreeType::LocalFunction: {
Expand Down Expand Up @@ -610,6 +635,11 @@ InferredType TypeInferencer::InferLocalVar(const std::shared_ptr<SyntaxTreeLocal
// 在重置 env_ 后重新注入,使函数特化试推断能看到正确类型。
if (!tctx.IsTrialInference() && tctx.env.IsAtFileScope() && IsNumericInferredType(type)) {
file_level_types_[names[i]] = type;
// 同时记录 initializer 节点:文件级数值字面量是常量。
// local x = func() 在预处理里已经改成 local x = nil,不会进这张表。
if (init_node) {
file_level_init_exps_.insert(init_node);
}
}
}

Expand Down Expand Up @@ -646,6 +676,12 @@ InferredType TypeInferencer::InferAssign(const std::shared_ptr<SyntaxTreeAssign>

if (const auto *init = tctx.env.LookupInitNode(name)) {
tctx.var_define_nodes[var.get()] = init;
// 文件级数值字面量是 static const,用户函数里再赋值直接报编译期错误。
// __fakelua_init 除外:local x = func() 不能做 C 静态初值,预处理把它改成
// local x = nil,并只在 __fakelua_init 里写一次 x = func()。那是初始化,不是再赋值。
if (!in_init_function_ && file_level_init_exps_.contains(init)) {
ThrowFakeluaException(std::format("cannot reassign file-level constant '{}' at {}", name, SyntaxTreeLocationStr(file_name_, assign)));
}
}

current_map[var.get()] = current;
Expand Down Expand Up @@ -1092,7 +1128,7 @@ EvalTypeSnapshot TypeInferencer::RunTrialInference(const SyntaxTreeInterfacePtr

// 运行函数体类型推断(不新开作用域,参数已在当前作用域中定义)。
// Trial 推断不消费 shadow 信息(shadow 只与 AST 结构相关,主推断已覆盖),
// 但 TraversalContext 需要一个引用,因此用一个丢弃式的 set 占位。
// 但 TraversalContext 需要一个引用,因此用丢弃式的容器占位。
std::set<std::pair<const SyntaxTreeInterface *, std::string>> dummy_shadowed_decls;
TraversalContext tctx{current_map, env, &ctx, var_define_nodes, dummy_shadowed_decls};
InferBlock(std::dynamic_pointer_cast<SyntaxTreeBlock>(func_block), false, tctx);
Expand Down
6 changes: 6 additions & 0 deletions src/compile/type_inferencer.h
Original file line number Diff line number Diff line change
Expand Up @@ -277,7 +277,13 @@ class TypeInferencer {

private:
State *s_ = nullptr;
std::string file_name_;
// 正在推断 __fakelua_init。它里面的 x = func() 是文件级复杂初值的唯一赋值点,不是再赋值。
bool in_init_function_ = false;
std::unordered_map<std::string, InferredType> file_level_types_;
// 文件级数值字面量 local 的 initializer 节点。InferAssign 用它判断赋值目标是不是
// 这条常量绑定(对函数内同名遮蔽免疫)。__fakelua_init 里的赋值不查这张表。
std::unordered_set<const SyntaxTreeInterface *> file_level_init_exps_;

// 不动点迭代轮次上限(实际通常 2 轮即可收敛)。
static constexpr int kMaxSpecIterations = 16;
Expand Down
4 changes: 4 additions & 0 deletions src/jit/tcc_handle.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,10 @@ TCCHandle::TCCHandle(State *s, const CompileConfig &cfg) {
tcc_add_symbol(tcc_state_, "FakeluaCallByName", reinterpret_cast<void *>(FakeluaCallByName));
tcc_add_symbol(tcc_state_, "FlEvalLoadClosure", reinterpret_cast<void *>(FlEvalLoadClosure));
tcc_add_symbol(tcc_state_, "FakeluaInterpCall", reinterpret_cast<void *>(FakeluaInterpCall));
tcc_add_symbol(tcc_state_, "FakeluaAllocMultiCVar", reinterpret_cast<void *>(FakeluaAllocMultiCVar));
tcc_add_symbol(tcc_state_, "FakeluaSetMultiCVarElement", reinterpret_cast<void *>(FakeluaSetMultiCVarElement));
tcc_add_symbol(tcc_state_, "FakeluaJitContextPush", reinterpret_cast<void *>(FakeluaJitContextPush));
tcc_add_symbol(tcc_state_, "FakeluaJitContextPop", reinterpret_cast<void *>(FakeluaJitContextPop));
tcc_add_symbol(tcc_state_, "FakeluaLogLua", reinterpret_cast<void *>(FakeluaLogLua));
tcc_add_symbol(tcc_state_, "GetLogLevel", reinterpret_cast<void *>(GetLogLevel));
tcc_define_symbol(tcc_state_, "FAKELUA_JIT_TYPE", std::to_string(static_cast<int>(JIT_TCC)).c_str());
Expand Down
15 changes: 15 additions & 0 deletions src/jit/vm.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,18 @@ extern "C" __attribute__((used)) void FakeluaSetMultiCVarElement(CVar *multi, in
inter::SetMultiCVarElement(*multi, idx, val);
}

// JIT 生成的 C 代码(TCC 是 C 编译器,用不了 C++ 的 State::JitContextScope)调用闭包
// 前后经这对接口维护"当前执行引擎"。返回旧值供 Pop 恢复,单线程无需原子操作。
extern "C" int FakeluaJitContextPush(State *s, int jit) {
const int prev = static_cast<int>(s->CurrentJit());
s->SetCurrentJit(static_cast<JITType>(jit));
return prev;
}

extern "C" void FakeluaJitContextPop(State *s, int prev) {
s->SetCurrentJit(static_cast<JITType>(prev));
}

static CVar CallByNameImpl(State *state, int jit_type, const char *name, int arg_num, const CVar *raw_arg_arr);

extern "C" __attribute__((used)) CVar FakeluaCallByName(State *state, int jit_type, const char *name, int arg_num, ...) {
Expand Down Expand Up @@ -70,6 +82,9 @@ extern "C" __attribute__((used)) CVar FakeluaCallByName(State *state, int jit_ty
}

static CVar CallByNameImpl(State *state, int jit_type, const char *name, int arg_num, const CVar *raw_arg_arr) {
// 记录"当前 Lua 调用方引擎":native 函数内登记的异步回调据此派回同一引擎。
// 作用域覆盖整个函数(含嵌套的 Lua 回调),退出时恢复外层引擎。
State::JitContextScope jit_scope(state, static_cast<JITType>(jit_type));
// 查找函数:优先 JIT,其次 C++ 原生
// 用 string_view 查表,避免每次调用都堆分配 std::string
const std::string_view func_name(name);
Expand Down
8 changes: 8 additions & 0 deletions src/jit/vm.h
Original file line number Diff line number Diff line change
Expand Up @@ -97,6 +97,14 @@ extern "C" CVar FakeluaCallByName(State *state, int jit_type, const char *name,

extern "C" CVar FlEvalLoadClosure(State *state, VarClosure *cl, int arg_num, const CVar *args);

extern "C" CVar FakeluaAllocMultiCVar(State *state, int count);

extern "C" void FakeluaSetMultiCVarElement(CVar *multi, int idx, CVar val);

extern "C" int FakeluaJitContextPush(State *s, int jit);

extern "C" void FakeluaJitContextPop(State *s, int prev);

// 数组版 FakeluaCallByName,供解释器使用
CVar CallByNameArgs(State *state, int jit_type, const char *name, int arg_num, const CVar *args);

Expand Down
Loading
Loading