!48 fix: 变量声明初始化寄存器别名导致内外层循环相互影响

Merge pull request !48 from Luke/bugfix/declare-init-aliasing-
This commit is contained in:
Luke 2025-07-30 00:40:06 +00:00 committed by Gitee
commit 025ea75f08
No known key found for this signature in database
GPG Key ID: 173E9B9CA92EEF8F
4 changed files with 83 additions and 7 deletions

11
.run/Bug2.run.xml Normal file
View File

@ -0,0 +1,11 @@
<component name="ProjectRunConfigurationManager">
<configuration default="false" name="Bug2" type="Application" factoryName="Application" folderName="BugFarm">
<option name="ALTERNATIVE_JRE_PATH" value="graalvm-ce-23" />
<option name="MAIN_CLASS_NAME" value="org.jcnc.snow.cli.SnowCLI" />
<module name="Snow" />
<option name="PROGRAM_PARAMETERS" value="compile run -d playground/BugFarm/Bug2 -o target/Bug2" />
<method v="2">
<option name="Make" enabled="true" />
</method>
</configuration>
</component>

View File

@ -0,0 +1,45 @@
module: Main
import: os
function: main
parameter:
return_type: int
body:
loop:
init:
declare outer_i: int = 1
cond:
outer_i <= 10
step:
outer_i = outer_i + 1
body:
print(outer_i)
loop:
init:
// 注意这一行使用了外层循环的变量 outer_i
declare inter_j: int = outer_i
cond:
inter_j <= 10
step:
inter_j = inter_j + 1
body:
end body
end loop
end body
end loop
return 0
end body
end function
function: print
parameter:
declare i1: int
return_type: void
body:
syscall("PRINT",i1)
end body
end function
end module

View File

@ -0,0 +1,11 @@
module: os
import: os
function: print
parameter:
declare i1: int
return_type: void
body:
syscall("PRINT",i1)
end body
end function
end module

View File

@ -98,21 +98,30 @@ public class StatementBuilder {
return;
}
if (stmt instanceof DeclarationNode decl) {
// 变量声明 int a = 1;
// 变量声明语句 int a = 1;
if (decl.getInitializer().isPresent()) {
// 声明时有初值
// 如果声明时有初 int a = b;
// 1. 设置声明变量的类型
// 1. 设置变量类型便于表达式求值/指令生成时推断类型信息
ctx.setVarType(decl.getType());
IRVirtualRegister r = expr.build(decl.getInitializer().get());
// 2. 为当前声明的变量分配一个全新的虚拟寄存器
// 这样可以保证该变量和初始值表达式中的变量物理上独立不会发生别名/串扰
IRVirtualRegister dest = ctx.newRegister();
// 2. 清除变量声明
// 3. 将初始值表达式的计算结果写入新分配的寄存器
// 即使初始值是某个已存在变量 outer_i这里是值的拷贝
expr.buildInto(decl.getInitializer().get(), dest);
// 4. 清理类型设置防止影响后续变量声明
ctx.clearVarType();
ctx.getScope().declare(decl.getName(), decl.getType(), r);
// 5. 在作用域内将变量名与新分配的寄存器进行绑定
// 这样后续对该变量的任何操作都只会影响 dest不会反向影响初值表达式中的源变量
ctx.getScope().declare(decl.getName(), decl.getType(), dest);
} else {
// 仅声明无初值
// 仅声明变量无初值 int a;
// 在作用域内声明并分配新寄存器但不进行初始化
ctx.getScope().declare(decl.getName(), decl.getType());
}
return;