Add "kind" argument to Get/SetVReg.
In order to determine where a register is promoted its necessary to know
the kind of use of the register.
Extend notion of precise-ness to numeric verifier register types.
Dump verifier output in oatdump.
Dump vregs with their location or constant value.
Introduce indenting ostream utility.
Change-Id: Ia3d29497877976bc24465484743bca08236e1768
diff --git a/src/verifier/reg_type.cc b/src/verifier/reg_type.cc
index e02fbf4..dc41ceb 100644
--- a/src/verifier/reg_type.cc
+++ b/src/verifier/reg_type.cc
@@ -25,19 +25,22 @@
static const char* type_strings[] = {
"Undefined",
"Conflict",
- "Boolean",
- "Byte",
- "Short",
- "Char",
- "Integer",
- "Float",
- "Long (Low Half)",
- "Long (High Half)",
- "Double (Low Half)",
- "Double (High Half)",
- "64-bit Constant (Low Half)",
- "64-bit Constant (High Half)",
- "32-bit Constant",
+ "boolean",
+ "byte",
+ "short",
+ "char",
+ "int",
+ "float",
+ "long (Low Half)",
+ "long (High Half)",
+ "double (Low Half)",
+ "double (High Half)",
+ "Precise 32-bit Constant",
+ "Imprecise 32-bit Constant",
+ "Precise 64-bit Constant (Low Half)",
+ "Precise 64-bit Constant (High Half)",
+ "Imprecise 64-bit Constant (Low Half)",
+ "Imprecise 64-bit Constant (High Half)",
"Unresolved Reference",
"Uninitialized Reference",
"Uninitialized This Reference",
@@ -81,14 +84,34 @@
} else if (IsConstant()) {
uint32_t val = ConstantValue();
if (val == 0) {
- result = "Zero";
+ CHECK(IsPreciseConstant());
+ result = "Zero/null";
} else {
+ result = IsPreciseConstant() ? "Precise " : "Imprecise ";
if (IsConstantShort()) {
- result = StringPrintf("32-bit Constant: %d", val);
+ result += StringPrintf("Constant: %d", val);
} else {
- result = StringPrintf("32-bit Constant: 0x%x", val);
+ result += StringPrintf("Constant: 0x%x", val);
}
}
+ } else if (IsConstantLo()) {
+ int32_t val = ConstantValueLo();
+ result = IsPreciseConstantLo() ? "Precise " : "Imprecise ";
+ if (val >= std::numeric_limits<jshort>::min() &&
+ val <= std::numeric_limits<jshort>::max()) {
+ result += StringPrintf("Low-half Constant: %d", val);
+ } else {
+ result += StringPrintf("Low-half Constant: 0x%x", val);
+ }
+ } else if (IsConstantHi()) {
+ int32_t val = ConstantValueHi();
+ result = IsPreciseConstantHi() ? "Precise " : "Imprecise ";
+ if (val >= std::numeric_limits<jshort>::min() &&
+ val <= std::numeric_limits<jshort>::max()) {
+ result += StringPrintf("High-half Constant: %d", val);
+ } else {
+ result += StringPrintf("High-half Constant: 0x%x", val);
+ }
} else {
result = type_strings[type_];
if (IsReferenceTypes()) {
@@ -104,13 +127,14 @@
}
const RegType& RegType::HighHalf(RegTypeCache* cache) const {
- CHECK(IsLowHalf());
+ DCHECK(IsLowHalf());
if (type_ == kRegTypeLongLo) {
return cache->FromType(kRegTypeLongHi);
} else if (type_ == kRegTypeDoubleLo) {
return cache->FromType(kRegTypeDoubleHi);
} else {
- return cache->FromType(kRegTypeConstHi);
+ DCHECK_EQ(type_, kRegTypeImpreciseConstLo);
+ return cache->FromType(kRegTypeImpreciseConstHi);
}
}
@@ -244,16 +268,32 @@
if (val1 >= 0 && val2 >= 0) {
// +ve1 MERGE +ve2 => MAX(+ve1, +ve2)
if (val1 >= val2) {
- return *this;
+ if (!IsPreciseConstant()) {
+ return *this;
+ } else {
+ return reg_types->FromCat1Const(val1, false);
+ }
} else {
- return incoming_type;
+ if (!incoming_type.IsPreciseConstant()) {
+ return incoming_type;
+ } else {
+ return reg_types->FromCat1Const(val2, false);
+ }
}
} else if (val1 < 0 && val2 < 0) {
// -ve1 MERGE -ve2 => MIN(-ve1, -ve2)
if (val1 <= val2) {
- return *this;
+ if (!IsPreciseConstant()) {
+ return *this;
+ } else {
+ return reg_types->FromCat1Const(val1, false);
+ }
} else {
- return incoming_type;
+ if (!incoming_type.IsPreciseConstant()) {
+ return incoming_type;
+ } else {
+ return reg_types->FromCat1Const(val2, false);
+ }
}
} else {
// Values are +ve and -ve, choose smallest signed type in which they both fit
@@ -275,6 +315,14 @@
return reg_types->IntConstant();
}
}
+ } else if (IsConstantLo() && incoming_type.IsConstantLo()) {
+ int32_t val1 = ConstantValueLo();
+ int32_t val2 = incoming_type.ConstantValueLo();
+ return reg_types->FromCat2ConstLo(val1 | val2, false);
+ } else if (IsConstantHi() && incoming_type.IsConstantHi()) {
+ int32_t val1 = ConstantValueHi();
+ int32_t val2 = incoming_type.ConstantValueHi();
+ return reg_types->FromCat2ConstHi(val1 | val2, false);
} else if (IsIntegralTypes() && incoming_type.IsIntegralTypes()) {
if (IsBooleanTypes() && incoming_type.IsBooleanTypes()) {
return reg_types->Boolean(); // boolean MERGE boolean => boolean