fix(qbe): QBE_EnsureLocal for all operands, uppercase hVar→0, char→w

This commit is contained in:
2026-06-02 13:29:38 +03:00
parent 0eadb8ab76
commit 319dcd9280
2 changed files with 42 additions and 24 deletions
+21 -12
View File
@@ -167,7 +167,9 @@ func QBE_EnsureLocal(val: String) -> String {
if c == 37 as char8 || c == 36 as char8 || c == 64 as char8 { return val; } // %, $, @ if c == 37 as char8 || c == 36 as char8 || c == 64 as char8 { return val; } // %, $, @
if c == 45 as char8 { return val; } // negative number if c == 45 as char8 { return val; } // negative number
if c >= 48 as char8 && c <= 57 as char8 { return val; } // digit if c >= 48 as char8 && c <= 57 as char8 { return val; } // digit
// Bare identifier: add % prefix // Uppercase: assume unresolved global/type, use 0
if c >= 65 as char8 && c <= 90 as char8 { return "0"; }
// Lowercase: assume local, add %
var prefix: String = "%"; var prefix: String = "%";
return String_Concat(prefix, val); return String_Concat(prefix, val);
} }
@@ -308,6 +310,13 @@ func QBE_EmitExpr(qbe: *QbeEmitter, node: *HirNode) -> String {
} }
ci = ci + 1; ci = ci + 1;
} }
// Uppercase names are unresolved types/modules — return 0
if node.strValue != null as String && !String_Eq(node.strValue, "") {
let fc: char8 = node.strValue[0];
if fc >= 65 as char8 && fc <= 90 as char8 {
return "0";
}
}
let tmp: String = QBE_FreshTemp(qbe); let tmp: String = QBE_FreshTemp(qbe);
let ty: String = QbeBackend_TypeWord(node.typeKind); let ty: String = QbeBackend_TypeWord(node.typeKind);
QBE_EmitIndent(qbe); QBE_EmitIndent(qbe);
@@ -370,9 +379,9 @@ func QBE_EmitExpr(qbe: *QbeEmitter, node: *HirNode) -> String {
QBE_Emit(qbe, cmpOp); QBE_Emit(qbe, cmpOp);
QBE_Emit(qbe, ty); QBE_Emit(qbe, ty);
QBE_Emit(qbe, " "); QBE_Emit(qbe, " ");
QBE_Emit(qbe, left); QBE_Emit(qbe, QBE_EnsureLocal(left));
QBE_Emit(qbe, ", "); QBE_Emit(qbe, ", ");
QBE_Emit(qbe, right); QBE_Emit(qbe, QBE_EnsureLocal(right));
QBE_EmitLine(qbe, ""); QBE_EmitLine(qbe, "");
// QBE comparisons produce word results; extend if needed // QBE comparisons produce word results; extend if needed
if !String_Eq(ty, "w") && !String_Eq(ty, "b") && !String_Eq(ty, "h") { if !String_Eq(ty, "w") && !String_Eq(ty, "b") && !String_Eq(ty, "h") {
@@ -411,9 +420,9 @@ func QBE_EmitExpr(qbe: *QbeEmitter, node: *HirNode) -> String {
QBE_Emit(qbe, " "); QBE_Emit(qbe, " ");
QBE_Emit(qbe, opName); QBE_Emit(qbe, opName);
QBE_Emit(qbe, " "); QBE_Emit(qbe, " ");
QBE_Emit(qbe, left); QBE_Emit(qbe, QBE_EnsureLocal(left));
QBE_Emit(qbe, ", "); QBE_Emit(qbe, ", ");
QBE_Emit(qbe, right); QBE_Emit(qbe, QBE_EnsureLocal(right));
QBE_EmitLine(qbe, ""); QBE_EmitLine(qbe, "");
return tmp; return tmp;
} }
@@ -426,7 +435,7 @@ func QBE_EmitExpr(qbe: *QbeEmitter, node: *HirNode) -> String {
let lEnd: String = QBE_FreshLabel(qbe); let lEnd: String = QBE_FreshLabel(qbe);
QBE_EmitIndent(qbe); QBE_EmitIndent(qbe);
QBE_Emit(qbe, "jnz "); QBE_Emit(qbe, "jnz ");
QBE_Emit(qbe, left); QBE_Emit(qbe, QBE_EnsureLocal(left));
QBE_Emit(qbe, ", "); QBE_Emit(qbe, ", ");
QBE_Emit(qbe, lTrue); QBE_Emit(qbe, lTrue);
QBE_Emit(qbe, ", "); QBE_Emit(qbe, ", ");
@@ -454,7 +463,7 @@ func QBE_EmitExpr(qbe: *QbeEmitter, node: *HirNode) -> String {
let lEnd: String = QBE_FreshLabel(qbe); let lEnd: String = QBE_FreshLabel(qbe);
QBE_EmitIndent(qbe); QBE_EmitIndent(qbe);
QBE_Emit(qbe, "jnz "); QBE_Emit(qbe, "jnz ");
QBE_Emit(qbe, left); QBE_Emit(qbe, QBE_EnsureLocal(left));
QBE_Emit(qbe, ", "); QBE_Emit(qbe, ", ");
QBE_Emit(qbe, lTrue); QBE_Emit(qbe, lTrue);
QBE_Emit(qbe, ", "); QBE_Emit(qbe, ", ");
@@ -494,11 +503,11 @@ func QBE_EmitExpr(qbe: *QbeEmitter, node: *HirNode) -> String {
if op == tkBang { if op == tkBang {
// xor with 1 to invert boolean // xor with 1 to invert boolean
QBE_Emit(qbe, " xor "); QBE_Emit(qbe, " xor ");
QBE_Emit(qbe, operand); QBE_Emit(qbe, QBE_EnsureLocal(operand));
QBE_Emit(qbe, ", 1"); QBE_Emit(qbe, ", 1");
} else { } else {
QBE_Emit(qbe, " sub 0, "); QBE_Emit(qbe, " sub 0, ");
QBE_Emit(qbe, operand); QBE_Emit(qbe, QBE_EnsureLocal(operand));
} }
QBE_EmitLine(qbe, ""); QBE_EmitLine(qbe, "");
return tmp; return tmp;
@@ -563,7 +572,7 @@ func QBE_EmitExpr(qbe: *QbeEmitter, node: *HirNode) -> String {
QBE_Emit(qbe, " load"); QBE_Emit(qbe, " load");
QBE_Emit(qbe, ty); QBE_Emit(qbe, ty);
QBE_Emit(qbe, " "); QBE_Emit(qbe, " ");
QBE_Emit(qbe, ptr); QBE_Emit(qbe, QBE_EnsureLocal(ptr));
QBE_EmitLine(qbe, ""); QBE_EmitLine(qbe, "");
return tmp; return tmp;
} }
@@ -671,7 +680,7 @@ func QBE_EmitStmt(qbe: *QbeEmitter, node: *HirNode) {
QBE_EmitIndent(qbe); QBE_EmitIndent(qbe);
QBE_Emit(qbe, "jnz "); QBE_Emit(qbe, "jnz ");
QBE_Emit(qbe, condVal); QBE_Emit(qbe, QBE_EnsureLocal(condVal));
QBE_Emit(qbe, ", "); QBE_Emit(qbe, ", ");
QBE_Emit(qbe, lThen); QBE_Emit(qbe, lThen);
QBE_Emit(qbe, ", "); QBE_Emit(qbe, ", ");
@@ -711,7 +720,7 @@ func QBE_EmitStmt(qbe: *QbeEmitter, node: *HirNode) {
let condVal: String = QBE_EmitExpr(qbe, node.child1); let condVal: String = QBE_EmitExpr(qbe, node.child1);
QBE_EmitIndent(qbe); QBE_EmitIndent(qbe);
QBE_Emit(qbe, "jnz "); QBE_Emit(qbe, "jnz ");
QBE_Emit(qbe, condVal); QBE_Emit(qbe, QBE_EnsureLocal(condVal));
QBE_Emit(qbe, ", "); QBE_Emit(qbe, ", ");
QBE_Emit(qbe, lBody); QBE_Emit(qbe, lBody);
QBE_Emit(qbe, ", "); QBE_Emit(qbe, ", ");
+21 -12
View File
@@ -167,7 +167,9 @@ func QBE_EnsureLocal(val: String) -> String {
if c == 37 as char8 || c == 36 as char8 || c == 64 as char8 { return val; } // %, $, @ if c == 37 as char8 || c == 36 as char8 || c == 64 as char8 { return val; } // %, $, @
if c == 45 as char8 { return val; } // negative number if c == 45 as char8 { return val; } // negative number
if c >= 48 as char8 && c <= 57 as char8 { return val; } // digit if c >= 48 as char8 && c <= 57 as char8 { return val; } // digit
// Bare identifier: add % prefix // Uppercase: assume unresolved global/type, use 0
if c >= 65 as char8 && c <= 90 as char8 { return "0"; }
// Lowercase: assume local, add %
var prefix: String = "%"; var prefix: String = "%";
return String_Concat(prefix, val); return String_Concat(prefix, val);
} }
@@ -308,6 +310,13 @@ func QBE_EmitExpr(qbe: *QbeEmitter, node: *HirNode) -> String {
} }
ci = ci + 1; ci = ci + 1;
} }
// Uppercase names are unresolved types/modules — return 0
if node.strValue != null as String && !String_Eq(node.strValue, "") {
let fc: char8 = node.strValue[0];
if fc >= 65 as char8 && fc <= 90 as char8 {
return "0";
}
}
let tmp: String = QBE_FreshTemp(qbe); let tmp: String = QBE_FreshTemp(qbe);
let ty: String = QbeBackend_TypeWord(node.typeKind); let ty: String = QbeBackend_TypeWord(node.typeKind);
QBE_EmitIndent(qbe); QBE_EmitIndent(qbe);
@@ -370,9 +379,9 @@ func QBE_EmitExpr(qbe: *QbeEmitter, node: *HirNode) -> String {
QBE_Emit(qbe, cmpOp); QBE_Emit(qbe, cmpOp);
QBE_Emit(qbe, ty); QBE_Emit(qbe, ty);
QBE_Emit(qbe, " "); QBE_Emit(qbe, " ");
QBE_Emit(qbe, left); QBE_Emit(qbe, QBE_EnsureLocal(left));
QBE_Emit(qbe, ", "); QBE_Emit(qbe, ", ");
QBE_Emit(qbe, right); QBE_Emit(qbe, QBE_EnsureLocal(right));
QBE_EmitLine(qbe, ""); QBE_EmitLine(qbe, "");
// QBE comparisons produce word results; extend if needed // QBE comparisons produce word results; extend if needed
if !String_Eq(ty, "w") && !String_Eq(ty, "b") && !String_Eq(ty, "h") { if !String_Eq(ty, "w") && !String_Eq(ty, "b") && !String_Eq(ty, "h") {
@@ -411,9 +420,9 @@ func QBE_EmitExpr(qbe: *QbeEmitter, node: *HirNode) -> String {
QBE_Emit(qbe, " "); QBE_Emit(qbe, " ");
QBE_Emit(qbe, opName); QBE_Emit(qbe, opName);
QBE_Emit(qbe, " "); QBE_Emit(qbe, " ");
QBE_Emit(qbe, left); QBE_Emit(qbe, QBE_EnsureLocal(left));
QBE_Emit(qbe, ", "); QBE_Emit(qbe, ", ");
QBE_Emit(qbe, right); QBE_Emit(qbe, QBE_EnsureLocal(right));
QBE_EmitLine(qbe, ""); QBE_EmitLine(qbe, "");
return tmp; return tmp;
} }
@@ -426,7 +435,7 @@ func QBE_EmitExpr(qbe: *QbeEmitter, node: *HirNode) -> String {
let lEnd: String = QBE_FreshLabel(qbe); let lEnd: String = QBE_FreshLabel(qbe);
QBE_EmitIndent(qbe); QBE_EmitIndent(qbe);
QBE_Emit(qbe, "jnz "); QBE_Emit(qbe, "jnz ");
QBE_Emit(qbe, left); QBE_Emit(qbe, QBE_EnsureLocal(left));
QBE_Emit(qbe, ", "); QBE_Emit(qbe, ", ");
QBE_Emit(qbe, lTrue); QBE_Emit(qbe, lTrue);
QBE_Emit(qbe, ", "); QBE_Emit(qbe, ", ");
@@ -454,7 +463,7 @@ func QBE_EmitExpr(qbe: *QbeEmitter, node: *HirNode) -> String {
let lEnd: String = QBE_FreshLabel(qbe); let lEnd: String = QBE_FreshLabel(qbe);
QBE_EmitIndent(qbe); QBE_EmitIndent(qbe);
QBE_Emit(qbe, "jnz "); QBE_Emit(qbe, "jnz ");
QBE_Emit(qbe, left); QBE_Emit(qbe, QBE_EnsureLocal(left));
QBE_Emit(qbe, ", "); QBE_Emit(qbe, ", ");
QBE_Emit(qbe, lTrue); QBE_Emit(qbe, lTrue);
QBE_Emit(qbe, ", "); QBE_Emit(qbe, ", ");
@@ -494,11 +503,11 @@ func QBE_EmitExpr(qbe: *QbeEmitter, node: *HirNode) -> String {
if op == tkBang { if op == tkBang {
// xor with 1 to invert boolean // xor with 1 to invert boolean
QBE_Emit(qbe, " xor "); QBE_Emit(qbe, " xor ");
QBE_Emit(qbe, operand); QBE_Emit(qbe, QBE_EnsureLocal(operand));
QBE_Emit(qbe, ", 1"); QBE_Emit(qbe, ", 1");
} else { } else {
QBE_Emit(qbe, " sub 0, "); QBE_Emit(qbe, " sub 0, ");
QBE_Emit(qbe, operand); QBE_Emit(qbe, QBE_EnsureLocal(operand));
} }
QBE_EmitLine(qbe, ""); QBE_EmitLine(qbe, "");
return tmp; return tmp;
@@ -563,7 +572,7 @@ func QBE_EmitExpr(qbe: *QbeEmitter, node: *HirNode) -> String {
QBE_Emit(qbe, " load"); QBE_Emit(qbe, " load");
QBE_Emit(qbe, ty); QBE_Emit(qbe, ty);
QBE_Emit(qbe, " "); QBE_Emit(qbe, " ");
QBE_Emit(qbe, ptr); QBE_Emit(qbe, QBE_EnsureLocal(ptr));
QBE_EmitLine(qbe, ""); QBE_EmitLine(qbe, "");
return tmp; return tmp;
} }
@@ -671,7 +680,7 @@ func QBE_EmitStmt(qbe: *QbeEmitter, node: *HirNode) {
QBE_EmitIndent(qbe); QBE_EmitIndent(qbe);
QBE_Emit(qbe, "jnz "); QBE_Emit(qbe, "jnz ");
QBE_Emit(qbe, condVal); QBE_Emit(qbe, QBE_EnsureLocal(condVal));
QBE_Emit(qbe, ", "); QBE_Emit(qbe, ", ");
QBE_Emit(qbe, lThen); QBE_Emit(qbe, lThen);
QBE_Emit(qbe, ", "); QBE_Emit(qbe, ", ");
@@ -711,7 +720,7 @@ func QBE_EmitStmt(qbe: *QbeEmitter, node: *HirNode) {
let condVal: String = QBE_EmitExpr(qbe, node.child1); let condVal: String = QBE_EmitExpr(qbe, node.child1);
QBE_EmitIndent(qbe); QBE_EmitIndent(qbe);
QBE_Emit(qbe, "jnz "); QBE_Emit(qbe, "jnz ");
QBE_Emit(qbe, condVal); QBE_Emit(qbe, QBE_EnsureLocal(condVal));
QBE_Emit(qbe, ", "); QBE_Emit(qbe, ", ");
QBE_Emit(qbe, lBody); QBE_Emit(qbe, lBody);
QBE_Emit(qbe, ", "); QBE_Emit(qbe, ", ");