[vm/compiler] Fix crashes in AOT X64 DEBUG compiler.
Rationale:
The method ConstructReplacementFor() in range analysis would unconditionally
replace an UnaryInt64Op with an UnaryUint32Op, regardless of whether it contains
an NEGATE or NOT. None of the backends supports a NEGATE UnaryUint32Op,
however (I added a missing assert to X64 for the future, even though we currently
found the issue in the constructor already). Note that alternatively we could implement
NEGATE UnaryUint32Op for all platforms.
Note:
A similar issue was found for TRUNCDIV with a second fuzz test, which is fixed
in same CL with a more general approach.
Bug:
https://github.com/dart-lang/sdk/issues/34678
https://github.com/dart-lang/sdk/issues/34679
Change-Id: I370268620008e5d4cb605c0bd11e423d8fcd5327
Reviewed-on: https://dart-review.googlesource.com/c/78148
Reviewed-by: Alexander Markov <alexmarkov@google.com>
Commit-Queue: Aart Bik <ajcbik@google.com>
diff --git a/runtime/vm/compiler/backend/il.h b/runtime/vm/compiler/backend/il.h
index ca93a55..b30532f 100644
--- a/runtime/vm/compiler/backend/il.h
+++ b/runtime/vm/compiler/backend/il.h
@@ -6165,7 +6165,7 @@
public:
UnaryUint32OpInstr(Token::Kind op_kind, Value* value, intptr_t deopt_id)
: UnaryIntegerOpInstr(op_kind, value, deopt_id) {
- ASSERT(op_kind == Token::kBIT_NOT);
+ ASSERT(IsSupported(op_kind));
}
virtual bool ComputeCanDeoptimize() const { return false; }
@@ -6179,6 +6179,10 @@
return kUnboxedUint32;
}
+ static bool IsSupported(Token::Kind op_kind) {
+ return op_kind == Token::kBIT_NOT;
+ }
+
DECLARE_INSTRUCTION(UnaryUint32Op)
private:
@@ -6420,9 +6424,9 @@
SetInputAt(1, right);
}
- static bool IsSupported(Token::Kind op, Value* left, Value* right) {
+ static bool IsSupported(Token::Kind op_kind, Value* left, Value* right) {
#if defined(TARGET_ARCH_IA32) || defined(TARGET_ARCH_ARM)
- switch (op) {
+ switch (op_kind) {
case Token::kADD:
case Token::kSUB:
case Token::kMUL:
@@ -6473,6 +6477,7 @@
intptr_t deopt_id)
: BinaryIntegerOpInstr(op_kind, left, right, deopt_id) {
mark_truncating();
+ ASSERT(IsSupported(op_kind));
}
virtual bool ComputeCanDeoptimize() const { return false; }
@@ -6486,6 +6491,20 @@
virtual CompileType ComputeType() const;
+ static bool IsSupported(Token::Kind op_kind) {
+ switch (op_kind) {
+ case Token::kADD:
+ case Token::kSUB:
+ case Token::kMUL:
+ case Token::kBIT_AND:
+ case Token::kBIT_OR:
+ case Token::kBIT_XOR:
+ return true;
+ default:
+ return false;
+ }
+ }
+
DECLARE_INSTRUCTION(BinaryUint32Op)
private:
diff --git a/runtime/vm/compiler/backend/il_x64.cc b/runtime/vm/compiler/backend/il_x64.cc
index eaea5db..687ecd0 100644
--- a/runtime/vm/compiler/backend/il_x64.cc
+++ b/runtime/vm/compiler/backend/il_x64.cc
@@ -6017,6 +6017,7 @@
}
DEFINE_BACKEND(UnaryUint32Op, (SameAsFirstInput, Register value)) {
+ ASSERT(instr->op_kind() == Token::kBIT_NOT);
__ notl(value);
}
diff --git a/runtime/vm/compiler/backend/range_analysis.cc b/runtime/vm/compiler/backend/range_analysis.cc
index 2319532..71fd853 100644
--- a/runtime/vm/compiler/backend/range_analysis.cc
+++ b/runtime/vm/compiler/backend/range_analysis.cc
@@ -1552,9 +1552,12 @@
// TODO(johnmccutchan): Consider Smi operations, to avoid unnecessary tagging
// & untagged of intermediate results.
// TODO(johnmccutchan): Consider phis.
- return def->IsBoxInt64() || def->IsUnboxInt64() || def->IsBinaryInt64Op() ||
- def->IsShiftInt64Op() || def->IsSpeculativeShiftInt64Op() ||
- def->IsUnaryInt64Op();
+ return def->IsBoxInt64() || def->IsUnboxInt64() || def->IsShiftInt64Op() ||
+ def->IsSpeculativeShiftInt64Op() ||
+ (def->IsBinaryInt64Op() && BinaryUint32OpInstr::IsSupported(
+ def->AsBinaryInt64Op()->op_kind())) ||
+ (def->IsUnaryInt64Op() &&
+ UnaryUint32OpInstr::IsSupported(def->AsUnaryInt64Op()->op_kind()));
}
void IntegerInstructionSelector::FindPotentialUint32Definitions() {