feat: 基本类型全类型比较支持

This commit is contained in:
zhangxun 2025-07-10 19:14:37 +08:00
parent 9d21eeace9
commit a69cbb868a
5 changed files with 107 additions and 16 deletions

View File

@ -145,7 +145,7 @@ public record ExpressionBuilder(IRContext ctx) {
if (ComparisonUtils.isComparisonOperator(op)) {
return InstructionFactory.binOp(
ctx,
ComparisonUtils.cmpOp(op, bin.left(), bin.right()),
ComparisonUtils.cmpOp(ctx.getScope().getVarTypes(), op, bin.left(), bin.right()),
left, right);
}
@ -171,7 +171,7 @@ public record ExpressionBuilder(IRContext ctx) {
if (ComparisonUtils.isComparisonOperator(op)) {
InstructionFactory.binOpInto(
ctx,
ComparisonUtils.cmpOp(op, bin.left(), bin.right()),
ComparisonUtils.cmpOp(ctx.getScope().getVarTypes(), op, bin.left(), bin.right()),
a, b, dest);
} else {
IROpCode code = ExpressionUtils.resolveOpCode(op, bin.left(), bin.right());

View File

@ -13,7 +13,7 @@ import java.util.Map;
* <ul>
* <li>维护在当前作用域中已声明变量的寄存器分配信息</li>
* <li>支持将已有虚拟寄存器与变量名重新绑定</li>
* <li>根据变量名查找对应的虚拟寄存器实例</li>
* <li>根据变量名查找对应的虚拟寄存器实例或类型</li>
* </ul>
*/
final class IRBuilderScope {
@ -104,4 +104,12 @@ final class IRBuilderScope {
String lookupType(String name) {
return varTypes.get(name);
}
/**
* 获取 变量->类型的映射 的不可变副本
* @return 变量->类型的映射 的不可变副本
*/
Map<String, String> getVarTypes() {
return Map.copyOf(varTypes);
}
}

View File

@ -218,7 +218,7 @@ public class StatementBuilder {
IRVirtualRegister b = expr.build(right);
// 使用适配后位宽正确的比较指令
IROpCode cmp = ComparisonUtils.cmpOp(operator, left, right);
IROpCode cmp = ComparisonUtils.cmpOp(ctx.getScope().getVarTypes(), operator, left, right);
IROpCode falseOp = IROpCodeUtils.invert(cmp);
InstructionFactory.cmpJump(ctx, falseOp, a, b, falseLabel);

View File

@ -2,6 +2,7 @@ package org.jcnc.snow.compiler.ir.utils;
import org.jcnc.snow.compiler.ir.core.IROpCode;
import org.jcnc.snow.compiler.ir.core.IROpCodeMappings;
import org.jcnc.snow.compiler.parser.ast.IdentifierNode;
import org.jcnc.snow.compiler.parser.ast.NumberLiteralNode;
import org.jcnc.snow.compiler.parser.ast.base.ExpressionNode;
import org.jcnc.snow.compiler.parser.ast.base.NodeContext;
@ -25,26 +26,108 @@ public final class ComparisonUtils {
return IROpCodeMappings.CMP_I32.containsKey(op);
}
/**
* <b>类型宽度优先级</b>D > F > L > I > S > B
* <ul>
* <li>Ddouble6</li>
* <li>Ffloat5</li>
* <li>Llong4</li>
* <li>Iint3</li>
* <li>Sshort2</li>
* <li>Bbyte1</li>
* <li>未识别类型0</li>
* </ul>
*
* @param p 类型标记字符
* @return 优先级数值越大类型越宽
*/
private static int rank(char p) {
return switch (p) {
case 'D' -> 6;
case 'F' -> 5;
case 'L' -> 4;
case 'I' -> 3;
case 'S' -> 2;
case 'B' -> 1;
default -> 0;
};
}
/**
* 返回更的公共类型即优先级高的类型
*
* @param a 类型标记字符 1
* @param b 类型标记字符 2
* @return 宽度更高的类型标记字符
*/
public static char promote(char a, char b) {
return rank(a) >= rank(b) ? a : b;
}
/**
* 返回符合操作数位宽的比较 IROpCode
*
* @param op 比较符号==, !=, <, >, <=, >=
* @param left 左操作数 AST
* @param right 右操作数 AST
* @param variables 变量->类型的映射
* @param op 比较符号==, !=, <, >, <=, >=
* @param left 左操作数 AST
* @param right 右操作数 AST
*/
public static IROpCode cmpOp(String op, ExpressionNode left, ExpressionNode right) {
boolean useLong = isLongLiteral(left) || isLongLiteral(right);
Map<String, IROpCode> table = useLong ? IROpCodeMappings.CMP_L64
: IROpCodeMappings.CMP_I32;
public static IROpCode cmpOp(Map<String, String> variables, String op, ExpressionNode left, ExpressionNode right) {
char typeLeft = analysisType(variables, left);
char typeRight = analysisType(variables, right);
char type = promote(typeLeft, typeRight);
Map<String, IROpCode> table = switch (type) {
case 'B' -> IROpCodeMappings.CMP_B8;
case 'S' -> IROpCodeMappings.CMP_S16;
case 'I' -> IROpCodeMappings.CMP_I32;
case 'L' -> IROpCodeMappings.CMP_L64;
case 'F' -> IROpCodeMappings.CMP_F32;
case 'D' -> IROpCodeMappings.CMP_D64;
default -> throw new IllegalStateException("Unexpected value: " + type);
};
return table.get(op);
}
/* ------------ 内部工具 ------------ */
private static boolean isLongLiteral(ExpressionNode node) {
private static char analysisType(Map<String, String> variables, ExpressionNode node) {
if (node instanceof NumberLiteralNode(String value, NodeContext _)) {
return value.endsWith("L") || value.endsWith("l");
char suffix = Character.toUpperCase(value.charAt(value.length() - 1));
if ("BSILFD".indexOf(suffix) != -1) {
return suffix;
}
if (value.indexOf('.') != -1) {
return 'D';
}
return 'I'; // 默认为 'I'
}
return false; // 变量暂不处理后续可扩展符号表查询
if (node instanceof IdentifierNode(String name, NodeContext _)) {
final String type = variables.get(name);
switch (type) {
case "byte" -> {
return 'B';
}
case "short" -> {
return 'S';
}
case "int" -> {
return 'I';
}
case "long" -> {
return 'L';
}
case "float" -> {
return 'F';
}
case "double" -> {
return 'D';
}
}
}
return 'I'; // 默认为 'I'
}
}

View File

@ -120,8 +120,8 @@ public final class ExpressionUtils {
/**
* 推荐调用根据左右表达式类型自动选择 int / long 比较指令
*/
public static IROpCode cmpOp(String op, ExpressionNode left, ExpressionNode right) {
return ComparisonUtils.cmpOp(op, left, right);
public static IROpCode cmpOp(Map<String, String> variables, String op, ExpressionNode left, ExpressionNode right) {
return ComparisonUtils.cmpOp(variables, op, left, right);
}
/* ──────────────── 类型推断 & 算术操作码匹配 ──────────────── */