步骤3:Codegen VAR_TEMP——初值装载(emit_temp_init)+ FB 内联 Temp 固定寄存器(nlocals 隔离临时区)+ VarRef/赋值 fallback
This commit is contained in:
@@ -120,6 +120,8 @@ namespace {
|
||||
std::vector<uint8_t> code; ///< 字节码(变长指令,字节流)
|
||||
std::map<std::string, uint8_t> regs; ///< 变量名 → 帧寄存器
|
||||
std::map<std::string, uint8_t> reg_func; ///< 变量名 → func(类型)
|
||||
std::map<std::string, uint8_t> fb_temp; ///< FB 内联 VAR_TEMP → 帧寄存器(当前内联层)
|
||||
std::map<std::string, uint8_t> fb_temp_func; ///< FB 内联 VAR_TEMP → func
|
||||
uint8_t nlocals = 0; ///< 变量区终点 = 临时寄存器起始
|
||||
uint8_t nregs = 0; ///< 寄存器峰值
|
||||
uint8_t temp_used = 0; ///< 本语句已用临时数
|
||||
@@ -266,6 +268,33 @@ namespace {
|
||||
return "int";
|
||||
}
|
||||
|
||||
/// VAR_TEMP 初值装载:对 temp_map 中每个变量 emit LOADK(声明初值或 0)。
|
||||
/// temp_map 键为变量名、值为 (寄存器, func);调用点开头执行 → 每次调用重新初始化。
|
||||
void emit_temp_init(FuncCtx& f, const POU& pou,
|
||||
const std::map<std::string, uint8_t>& map,
|
||||
const std::map<std::string, uint8_t>& func_map) {
|
||||
for (const VarBlock& b : pou.blocks) {
|
||||
if (b.section != VarSection::Temp) {
|
||||
continue;
|
||||
}
|
||||
for (const VarDecl& d : b.vars) {
|
||||
const auto it = map.find(d.name);
|
||||
if (it == map.end()) {
|
||||
continue;
|
||||
}
|
||||
const uint8_t func = func_map.count(d.name)
|
||||
? func_map.at(d.name)
|
||||
: func_of_name("INT");
|
||||
int64_t v = d.has_init ? d.init_value : 0;
|
||||
if (d.has_init && d.type.name == "bool") {
|
||||
v = d.init_value ? 1 : 0;
|
||||
}
|
||||
const size_t s = E_imm(f, "LOADK", it->second, const_id(v));
|
||||
set_func(f.code.data() + s, func);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
bool build_function(const POU& pou, FuncCtx* f) {
|
||||
if (pou.kind == PouKind::FunctionBlock) {
|
||||
f->nlocals = 8;
|
||||
@@ -320,6 +349,7 @@ namespace {
|
||||
}
|
||||
map_->funcs.emplace_back(f->name, vars);
|
||||
}
|
||||
emit_temp_init(*f, pou, f->regs, f->reg_func);
|
||||
for (const Stmt& st : pou.body) {
|
||||
begin_stmt(*f);
|
||||
if (!compile_stmt(*f, st)) {
|
||||
@@ -363,6 +393,18 @@ namespace {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
const auto tit = f.fb_temp.find(st.target);
|
||||
if (tit != f.fb_temp.end()) {
|
||||
const uint8_t t = alloc_temp(f);
|
||||
const uint8_t tf_ = f.fb_temp_func.count(st.target)
|
||||
? f.fb_temp_func.at(st.target)
|
||||
: func_of_name("INT");
|
||||
if (!compile_expr(f, *st.value, t, tf_)) {
|
||||
return false;
|
||||
}
|
||||
E_rr(f, "MOVE", tit->second, t);
|
||||
return true;
|
||||
}
|
||||
const auto it = f.regs.find(st.target);
|
||||
if (it == f.regs.end()) {
|
||||
return store_target(f, st.target, *st.value);
|
||||
@@ -421,12 +463,36 @@ namespace {
|
||||
bool compile_fb_inline(FuncCtx& f, const POU& fb, const InstFields& inst) {
|
||||
const InstFields* saved = inline_fields_;
|
||||
inline_fields_ = &inst;
|
||||
// VAR_TEMP:本调用点分配独立固定寄存器(MAIN 帧,nregs 之后),
|
||||
// 内联体开头装载初值 → 每次调用重新初始化;嵌套内联 save/restore
|
||||
const std::map<std::string, uint8_t> saved_temp = f.fb_temp;
|
||||
const std::map<std::string, uint8_t> saved_temp_func = f.fb_temp_func;
|
||||
f.fb_temp.clear();
|
||||
f.fb_temp_func.clear();
|
||||
for (const VarBlock& b : fb.blocks) {
|
||||
if (b.section != VarSection::Temp) {
|
||||
continue;
|
||||
}
|
||||
for (const VarDecl& d : b.vars) {
|
||||
if (d.type.kind != TypeKind::Scalar) {
|
||||
continue;
|
||||
}
|
||||
const uint8_t r = f.nregs++;
|
||||
f.fb_temp[d.name] = r;
|
||||
f.fb_temp_func[d.name] = func_of_name(type_name_of_var(fb, d.name));
|
||||
}
|
||||
}
|
||||
// 临时寄存器起点提到 Temp 区之上,避免语句内 alloc_temp 撞上 Temp 寄存器
|
||||
f.nlocals = f.nregs;
|
||||
emit_temp_init(f, fb, f.fb_temp, f.fb_temp_func);
|
||||
for (const Stmt& s : fb.body) {
|
||||
begin_stmt(f);
|
||||
if (!compile_stmt(f, s)) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
f.fb_temp = saved_temp;
|
||||
f.fb_temp_func = saved_temp_func;
|
||||
inline_fields_ = saved;
|
||||
return true;
|
||||
}
|
||||
@@ -554,6 +620,15 @@ namespace {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
const auto tit = f.fb_temp.find(e.name);
|
||||
if (tit != f.fb_temp.end()) {
|
||||
const size_t s = E_rr(f, "MOVE", rd, tit->second);
|
||||
const auto tf = f.fb_temp_func.find(e.name);
|
||||
set_func(f.code.data() + s,
|
||||
tf != f.fb_temp_func.end() ? tf->second
|
||||
: func_of_name("INT"));
|
||||
return true;
|
||||
}
|
||||
const auto sit = f.regs.find(e.name);
|
||||
if (sit != f.regs.end()) {
|
||||
const size_t s = E_rr(f, "MOVE", rd, sit->second);
|
||||
|
||||
Reference in New Issue
Block a user