diff --git a/src/main/java/org/jcnc/snow/compiler/ir/builder/ExpressionBuilder.java b/src/main/java/org/jcnc/snow/compiler/ir/builder/ExpressionBuilder.java index f53d8cc..bb8c32e 100644 --- a/src/main/java/org/jcnc/snow/compiler/ir/builder/ExpressionBuilder.java +++ b/src/main/java/org/jcnc/snow/compiler/ir/builder/ExpressionBuilder.java @@ -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()); diff --git a/src/main/java/org/jcnc/snow/compiler/ir/builder/IRBuilderScope.java b/src/main/java/org/jcnc/snow/compiler/ir/builder/IRBuilderScope.java index e0fd4cf..3cd5deb 100644 --- a/src/main/java/org/jcnc/snow/compiler/ir/builder/IRBuilderScope.java +++ b/src/main/java/org/jcnc/snow/compiler/ir/builder/IRBuilderScope.java @@ -13,7 +13,7 @@ import java.util.Map; * */ final class IRBuilderScope { @@ -104,4 +104,12 @@ final class IRBuilderScope { String lookupType(String name) { return varTypes.get(name); } + + /** + * 获取 变量->类型的映射 的不可变副本 + * @return 变量->类型的映射 的不可变副本 + */ + Map getVarTypes() { + return Map.copyOf(varTypes); + } } diff --git a/src/main/java/org/jcnc/snow/compiler/ir/builder/StatementBuilder.java b/src/main/java/org/jcnc/snow/compiler/ir/builder/StatementBuilder.java index 78e42fa..30d672a 100644 --- a/src/main/java/org/jcnc/snow/compiler/ir/builder/StatementBuilder.java +++ b/src/main/java/org/jcnc/snow/compiler/ir/builder/StatementBuilder.java @@ -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); diff --git a/src/main/java/org/jcnc/snow/compiler/ir/utils/ComparisonUtils.java b/src/main/java/org/jcnc/snow/compiler/ir/utils/ComparisonUtils.java index 70ac8f5..3cc8e37 100644 --- a/src/main/java/org/jcnc/snow/compiler/ir/utils/ComparisonUtils.java +++ b/src/main/java/org/jcnc/snow/compiler/ir/utils/ComparisonUtils.java @@ -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); } + /** + * 类型宽度优先级:D > F > L > I > S > B + * + * + * @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 table = useLong ? IROpCodeMappings.CMP_L64 - : IROpCodeMappings.CMP_I32; + public static IROpCode cmpOp(Map variables, String op, ExpressionNode left, ExpressionNode right) { + char typeLeft = analysisType(variables, left); + char typeRight = analysisType(variables, right); + char type = promote(typeLeft, typeRight); + + Map 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 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' } } diff --git a/src/main/java/org/jcnc/snow/compiler/ir/utils/ExpressionUtils.java b/src/main/java/org/jcnc/snow/compiler/ir/utils/ExpressionUtils.java index 2eed575..ba6f663 100644 --- a/src/main/java/org/jcnc/snow/compiler/ir/utils/ExpressionUtils.java +++ b/src/main/java/org/jcnc/snow/compiler/ir/utils/ExpressionUtils.java @@ -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 variables, String op, ExpressionNode left, ExpressionNode right) { + return ComparisonUtils.cmpOp(variables, op, left, right); } /* ──────────────── 类型推断 & 算术操作码匹配 ──────────────── */