fix: 变量的类型受右值类型影响而降级
This commit is contained in:
parent
e78cb09c0f
commit
ee9e56c479
@ -109,7 +109,7 @@ public record ExpressionBuilder(IRContext ctx) {
|
|||||||
switch (node) {
|
switch (node) {
|
||||||
// 数字字面量,直接加载到目标寄存器
|
// 数字字面量,直接加载到目标寄存器
|
||||||
case NumberLiteralNode n ->
|
case NumberLiteralNode n ->
|
||||||
InstructionFactory.loadConstInto(ctx, dest, ExpressionUtils.parseIntSafely(n.value()));
|
InstructionFactory.loadConstInto(ctx, dest, ExpressionUtils.buildNumberConstant(ctx, n.value()));
|
||||||
// 标识符,查找并move到目标寄存器
|
// 标识符,查找并move到目标寄存器
|
||||||
case IdentifierNode id -> {
|
case IdentifierNode id -> {
|
||||||
IRVirtualRegister src = ctx.getScope().lookup(id.name());
|
IRVirtualRegister src = ctx.getScope().lookup(id.name());
|
||||||
@ -207,7 +207,7 @@ public record ExpressionBuilder(IRContext ctx) {
|
|||||||
* @return 存放该常量的寄存器
|
* @return 存放该常量的寄存器
|
||||||
*/
|
*/
|
||||||
private IRVirtualRegister buildNumberLiteral(String value) {
|
private IRVirtualRegister buildNumberLiteral(String value) {
|
||||||
IRConstant constant = ExpressionUtils.buildNumberConstant(value);
|
IRConstant constant = ExpressionUtils.buildNumberConstant(ctx, value);
|
||||||
IRVirtualRegister reg = ctx.newRegister();
|
IRVirtualRegister reg = ctx.newRegister();
|
||||||
ctx.addInstruction(new LoadConstInstruction(reg, constant));
|
ctx.addInstruction(new LoadConstInstruction(reg, constant));
|
||||||
return reg;
|
return reg;
|
||||||
|
|||||||
@ -51,7 +51,7 @@ public class FunctionBuilder {
|
|||||||
// 2) 声明形参:为每个参数分配虚拟寄存器并声明到作用域
|
// 2) 声明形参:为每个参数分配虚拟寄存器并声明到作用域
|
||||||
for (ParameterNode p : functionNode.parameters()) {
|
for (ParameterNode p : functionNode.parameters()) {
|
||||||
IRVirtualRegister reg = irFunction.newRegister(); // 新寄存器
|
IRVirtualRegister reg = irFunction.newRegister(); // 新寄存器
|
||||||
irContext.getScope().declare(p.name(), reg); // 变量名→寄存器绑定
|
irContext.getScope().declare(p.name(), p.type(), reg); // 变量名→寄存器绑定
|
||||||
irFunction.addParameter(reg); // 添加到函数参数列表
|
irFunction.addParameter(reg); // 添加到函数参数列表
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -24,6 +24,13 @@ final class IRBuilderScope {
|
|||||||
*/
|
*/
|
||||||
private final Map<String, IRVirtualRegister> vars = new HashMap<>();
|
private final Map<String, IRVirtualRegister> vars = new HashMap<>();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 存储变量名到对应类型的映射。
|
||||||
|
* <br>
|
||||||
|
* 变量名为键,变量类型为值,用于变量类型提升。
|
||||||
|
*/
|
||||||
|
private final Map<String, String> varTypes = new HashMap<>();
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 当前作用域所绑定的 IRFunction 对象,用于申请新的虚拟寄存器。
|
* 当前作用域所绑定的 IRFunction 对象,用于申请新的虚拟寄存器。
|
||||||
*/
|
*/
|
||||||
@ -44,10 +51,12 @@ final class IRBuilderScope {
|
|||||||
* 调用绑定的 IRFunction.newRegister() 生成寄存器后保存到映射表中。
|
* 调用绑定的 IRFunction.newRegister() 生成寄存器后保存到映射表中。
|
||||||
*
|
*
|
||||||
* @param name 变量名称,作为映射键使用
|
* @param name 变量名称,作为映射键使用
|
||||||
|
* @param type 变量类型
|
||||||
*/
|
*/
|
||||||
void declare(String name) {
|
void declare(String name, String type) {
|
||||||
IRVirtualRegister reg = fn.newRegister();
|
IRVirtualRegister reg = fn.newRegister();
|
||||||
vars.put(name, reg);
|
vars.put(name, reg);
|
||||||
|
varTypes.put(name, type);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -55,10 +64,12 @@ final class IRBuilderScope {
|
|||||||
* 该方法可用于将外部或前一作用域的寄存器导入到本作用域。
|
* 该方法可用于将外部或前一作用域的寄存器导入到本作用域。
|
||||||
*
|
*
|
||||||
* @param name 变量名称,作为映射键使用
|
* @param name 变量名称,作为映射键使用
|
||||||
|
* @param type 变量类型
|
||||||
* @param reg 要绑定到该名称的 IRVirtualRegister 实例
|
* @param reg 要绑定到该名称的 IRVirtualRegister 实例
|
||||||
*/
|
*/
|
||||||
void declare(String name, IRVirtualRegister reg) {
|
void declare(String name, String type, IRVirtualRegister reg) {
|
||||||
vars.put(name, reg);
|
vars.put(name, reg);
|
||||||
|
varTypes.put(name, type);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -82,4 +93,15 @@ final class IRBuilderScope {
|
|||||||
IRVirtualRegister lookup(String name) {
|
IRVirtualRegister lookup(String name) {
|
||||||
return vars.get(name);
|
return vars.get(name);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 根据变量名称在当前作用域中查找对应的类型。
|
||||||
|
*
|
||||||
|
* @param name 需要查询的变量名称
|
||||||
|
* @return 如果该名称已声明,则返回对应的类型
|
||||||
|
* 如果未声明,则返回 null
|
||||||
|
*/
|
||||||
|
String lookupType(String name) {
|
||||||
|
return varTypes.get(name);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -4,6 +4,8 @@ import org.jcnc.snow.compiler.ir.core.IRFunction;
|
|||||||
import org.jcnc.snow.compiler.ir.core.IRInstruction;
|
import org.jcnc.snow.compiler.ir.core.IRInstruction;
|
||||||
import org.jcnc.snow.compiler.ir.value.IRVirtualRegister;
|
import org.jcnc.snow.compiler.ir.value.IRVirtualRegister;
|
||||||
|
|
||||||
|
import java.util.Optional;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* IRContext 类负责封装当前正在构建的 IRFunction 实例
|
* IRContext 类负责封装当前正在构建的 IRFunction 实例
|
||||||
* 以及与之配套的作用域管理(IRBuilderScope),
|
* 以及与之配套的作用域管理(IRBuilderScope),
|
||||||
@ -31,6 +33,11 @@ public class IRContext {
|
|||||||
*/
|
*/
|
||||||
private final IRBuilderScope scope;
|
private final IRBuilderScope scope;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 当前声明变量的类型,不在声明变量时为空
|
||||||
|
*/
|
||||||
|
private Optional<String> var_type;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 构造一个新的 IRContext,并将指定的 IRFunction 与作用域关联。
|
* 构造一个新的 IRContext,并将指定的 IRFunction 与作用域关联。
|
||||||
*
|
*
|
||||||
@ -41,6 +48,7 @@ public class IRContext {
|
|||||||
this.scope = new IRBuilderScope();
|
this.scope = new IRBuilderScope();
|
||||||
// 关联作用域与 IRFunction,以便在声明变量时申请寄存器
|
// 关联作用域与 IRFunction,以便在声明变量时申请寄存器
|
||||||
this.scope.attachFunction(function);
|
this.scope.attachFunction(function);
|
||||||
|
this.var_type = Optional.empty();
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -85,4 +93,29 @@ public class IRContext {
|
|||||||
public String newLabel() {
|
public String newLabel() {
|
||||||
return "L" + (labelCounter++);
|
return "L" + (labelCounter++);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 获取当前 declare 编译阶段变量类型
|
||||||
|
*
|
||||||
|
* @return 当前 declare 的变量类型
|
||||||
|
*/
|
||||||
|
public Optional<String> getVarType() {
|
||||||
|
return var_type;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 设置当前 declare 编译阶段变量类型
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
public void setVarType(String type) {
|
||||||
|
this.var_type = Optional.of(type);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 清除当前 declare 编译阶段变量类型
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
public void clearVarType() {
|
||||||
|
this.var_type = Optional.empty();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -58,8 +58,8 @@ public class InstructionFactory {
|
|||||||
* @param dest 目标寄存器
|
* @param dest 目标寄存器
|
||||||
* @param value 要加载的整数常量
|
* @param value 要加载的整数常量
|
||||||
*/
|
*/
|
||||||
public static void loadConstInto(IRContext ctx, IRVirtualRegister dest, int value) {
|
public static void loadConstInto(IRContext ctx, IRVirtualRegister dest, IRConstant value) {
|
||||||
ctx.addInstruction(new LoadConstInstruction(dest, new IRConstant(value)));
|
ctx.addInstruction(new LoadConstInstruction(dest, value));
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|||||||
@ -55,19 +55,37 @@ public class StatementBuilder {
|
|||||||
}
|
}
|
||||||
if (stmt instanceof AssignmentNode(String var, ExpressionNode rhs)) {
|
if (stmt instanceof AssignmentNode(String var, ExpressionNode rhs)) {
|
||||||
// 赋值语句,如 a = b + 1;
|
// 赋值语句,如 a = b + 1;
|
||||||
IRVirtualRegister target = getOrDeclareRegister(var);
|
|
||||||
|
final String type = ctx.getScope().lookupType(var);
|
||||||
|
|
||||||
|
// 1. 设置声明变量的类型
|
||||||
|
ctx.setVarType(type);
|
||||||
|
|
||||||
|
IRVirtualRegister target = getOrDeclareRegister(var, type);
|
||||||
expr.buildInto(rhs, target);
|
expr.buildInto(rhs, target);
|
||||||
|
|
||||||
|
// 2. 清除变量声明
|
||||||
|
ctx.clearVarType();
|
||||||
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
if (stmt instanceof DeclarationNode decl) {
|
if (stmt instanceof DeclarationNode decl) {
|
||||||
// 变量声明,如 int a = 1;
|
// 变量声明,如 int a = 1;
|
||||||
if (decl.getInitializer().isPresent()) {
|
if (decl.getInitializer().isPresent()) {
|
||||||
// 声明同时有初值
|
// 声明同时有初值
|
||||||
|
|
||||||
|
// 1. 设置声明变量的类型
|
||||||
|
ctx.setVarType(decl.getType());
|
||||||
|
|
||||||
IRVirtualRegister r = expr.build(decl.getInitializer().get());
|
IRVirtualRegister r = expr.build(decl.getInitializer().get());
|
||||||
ctx.getScope().declare(decl.getName(), r);
|
|
||||||
|
// 2. 清除变量声明
|
||||||
|
ctx.clearVarType();
|
||||||
|
|
||||||
|
ctx.getScope().declare(decl.getName(), decl.getType(), r);
|
||||||
} else {
|
} else {
|
||||||
// 仅声明,无初值
|
// 仅声明,无初值
|
||||||
ctx.getScope().declare(decl.getName());
|
ctx.getScope().declare(decl.getName(), decl.getType());
|
||||||
}
|
}
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@ -92,11 +110,12 @@ public class StatementBuilder {
|
|||||||
* @param name 变量名
|
* @param name 变量名
|
||||||
* @return 变量对应的虚拟寄存器
|
* @return 变量对应的虚拟寄存器
|
||||||
*/
|
*/
|
||||||
private IRVirtualRegister getOrDeclareRegister(String name) {
|
private IRVirtualRegister getOrDeclareRegister(String name, String type) {
|
||||||
IRVirtualRegister reg = ctx.getScope().lookup(name);
|
IRVirtualRegister reg = ctx.getScope().lookup(name);
|
||||||
if (reg == null) {
|
if (reg == null) {
|
||||||
reg = ctx.newRegister();
|
reg = ctx.newRegister();
|
||||||
ctx.getScope().declare(name, reg);
|
ctx.getScope().declare(name, type, reg);
|
||||||
|
throw new IllegalStateException("这里是怎么到达?");
|
||||||
}
|
}
|
||||||
return reg;
|
return reg;
|
||||||
}
|
}
|
||||||
|
|||||||
@ -1,5 +1,6 @@
|
|||||||
package org.jcnc.snow.compiler.ir.utils;
|
package org.jcnc.snow.compiler.ir.utils;
|
||||||
|
|
||||||
|
import org.jcnc.snow.compiler.ir.builder.IRContext;
|
||||||
import org.jcnc.snow.compiler.ir.core.IROpCode;
|
import org.jcnc.snow.compiler.ir.core.IROpCode;
|
||||||
import org.jcnc.snow.compiler.ir.core.IROpCodeMappings;
|
import org.jcnc.snow.compiler.ir.core.IROpCodeMappings;
|
||||||
import org.jcnc.snow.compiler.ir.value.IRConstant;
|
import org.jcnc.snow.compiler.ir.value.IRConstant;
|
||||||
@ -56,14 +57,29 @@ public class ExpressionUtils {
|
|||||||
* 根据数字字面量字符串自动判断类型,生成对应类型的 IRConstant。
|
* 根据数字字面量字符串自动判断类型,生成对应类型的 IRConstant。
|
||||||
* 支持 b/s/l/f/d 类型后缀与浮点格式,自动分配合适类型。
|
* 支持 b/s/l/f/d 类型后缀与浮点格式,自动分配合适类型。
|
||||||
*
|
*
|
||||||
|
* @param ctx IR 编译上下文环境
|
||||||
* @param value 字面量字符串(如 "1", "2l", "3.14f", "5D")
|
* @param value 字面量字符串(如 "1", "2l", "3.14f", "5D")
|
||||||
* @return 生成的 IRConstant 对象,包含正确类型
|
* @return 生成的 IRConstant 对象,包含正确类型
|
||||||
*/
|
*/
|
||||||
public static IRConstant buildNumberConstant(String value) {
|
public static IRConstant buildNumberConstant(IRContext ctx, String value) {
|
||||||
char suffix = value.isEmpty() ? '\0' : Character.toLowerCase(value.charAt(value.length() - 1));
|
char suffix = value.isEmpty() ? '\0' : Character.toLowerCase(value.charAt(value.length() - 1));
|
||||||
String digits = switch (suffix) {
|
String digits = switch (suffix) {
|
||||||
case 'b','s','l','f','d' -> value.substring(0, value.length() - 1);
|
case 'b','s','l','f','d' -> value.substring(0, value.length() - 1);
|
||||||
default -> value;
|
default -> {
|
||||||
|
if (ctx.getVarType().isPresent()) {
|
||||||
|
final var receiverType = ctx.getVarType().get();
|
||||||
|
switch (receiverType) {
|
||||||
|
case "byte" -> suffix = 'b';
|
||||||
|
case "short" -> suffix = 's';
|
||||||
|
case "int" -> suffix = 'i';
|
||||||
|
case "long" -> suffix = 'l';
|
||||||
|
case "float" -> suffix = 'f';
|
||||||
|
case "double" -> suffix = 'd';
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
yield value;
|
||||||
|
}
|
||||||
};
|
};
|
||||||
// 根据类型后缀或数值格式创建常量
|
// 根据类型后缀或数值格式创建常量
|
||||||
return switch (suffix) {
|
return switch (suffix) {
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user