Allow constant multiply both ways.
asm.js permits both: int * constant constant * int It does not, however, allow intishes in multiplies. BUG= https://code.google.com/p/v8/issues/detail?id=4203 TEST=mjsunit/asm-wasm,test-asm-validator R=aseemgarg@chromium.org,titzer@chromium.org LOG=N Review URL: https://codereview.chromium.org/1718083004 Cr-Commit-Position: refs/heads/master@{#34222}
This commit is contained in:
parent
943650784a
commit
0dd24015fb
@ -690,7 +690,7 @@ void AsmTyper::VisitAssignment(Assignment* expr) {
|
||||
expected_type_ = target_type;
|
||||
VisitVariableProxy(expr->target()->AsVariableProxy(), true);
|
||||
} else if (expr->target()->IsProperty()) {
|
||||
int value_intish = intish_;
|
||||
int32_t value_intish = intish_;
|
||||
Property* property = expr->target()->AsProperty();
|
||||
RECURSE(VisitWithExpectation(property->obj(), Type::Any(),
|
||||
"bad propety object"));
|
||||
@ -1083,7 +1083,7 @@ void AsmTyper::VisitIntegerBitwiseOperator(BinaryOperation* expr,
|
||||
Type* result_type, bool conversion) {
|
||||
RECURSE(VisitWithExpectation(expr->left(), Type::Number(),
|
||||
"left bitwise operand expected to be a number"));
|
||||
int left_intish = intish_;
|
||||
int32_t left_intish = intish_;
|
||||
Type* left_type = computed_type_;
|
||||
if (!left_type->Is(left_expected)) {
|
||||
FAIL(expr->left(), "left bitwise operand expected to be an integer");
|
||||
@ -1095,7 +1095,7 @@ void AsmTyper::VisitIntegerBitwiseOperator(BinaryOperation* expr,
|
||||
RECURSE(
|
||||
VisitWithExpectation(expr->right(), Type::Number(),
|
||||
"right bitwise operand expected to be a number"));
|
||||
int right_intish = intish_;
|
||||
int32_t right_intish = intish_;
|
||||
Type* right_type = computed_type_;
|
||||
if (!right_type->Is(right_expected)) {
|
||||
FAIL(expr->right(), "right bitwise operand expected to be an integer");
|
||||
@ -1204,28 +1204,33 @@ void AsmTyper::VisitBinaryOperation(BinaryOperation* expr) {
|
||||
expr->left(), Type::Number(),
|
||||
"left arithmetic operand expected to be number"));
|
||||
Type* left_type = computed_type_;
|
||||
int left_intish = intish_;
|
||||
int32_t left_intish = intish_;
|
||||
RECURSE(VisitWithExpectation(
|
||||
expr->right(), Type::Number(),
|
||||
"right arithmetic operand expected to be number"));
|
||||
Type* right_type = computed_type_;
|
||||
int right_intish = intish_;
|
||||
int32_t right_intish = intish_;
|
||||
Type* type = Type::Union(left_type, right_type, zone());
|
||||
if (type->Is(cache_.kAsmInt)) {
|
||||
if (expr->op() == Token::MUL) {
|
||||
Literal* right = expr->right()->AsLiteral();
|
||||
if (!right) {
|
||||
FAIL(expr, "direct integer multiply forbidden");
|
||||
}
|
||||
if (!right->value()->IsNumber()) {
|
||||
FAIL(expr, "multiply must be by an integer");
|
||||
}
|
||||
int32_t i;
|
||||
if (!right->value()->ToInt32(&i)) {
|
||||
FAIL(expr, "multiply must be a signed integer");
|
||||
Literal* left = expr->left()->AsLiteral();
|
||||
Literal* right = expr->right()->AsLiteral();
|
||||
if (left != nullptr && left->value()->IsNumber() &&
|
||||
left->value()->ToInt32(&i)) {
|
||||
if (right_intish != 0) {
|
||||
FAIL(expr, "intish not allowed in multiply");
|
||||
}
|
||||
} else if (right != nullptr && right->value()->IsNumber() &&
|
||||
right->value()->ToInt32(&i)) {
|
||||
if (left_intish != 0) {
|
||||
FAIL(expr, "intish not allowed in multiply");
|
||||
}
|
||||
} else {
|
||||
FAIL(expr, "multiply must be by an integer literal");
|
||||
}
|
||||
i = abs(i);
|
||||
if (i >= 1 << 20) {
|
||||
if (i >= (1 << 20)) {
|
||||
FAIL(expr, "multiply must be by value in -2^20 < n < 2^20");
|
||||
}
|
||||
intish_ = i;
|
||||
|
@ -92,7 +92,7 @@ class AsmTyper : public AstVisitor {
|
||||
Type* expected_type_;
|
||||
Type* computed_type_;
|
||||
VariableInfo* property_info_;
|
||||
int intish_; // How many ops we've gone without a x|0.
|
||||
int32_t intish_; // How many ops we've gone without a x|0.
|
||||
|
||||
Type* return_type_; // Return type of last function.
|
||||
size_t array_size_; // Array size of last ArrayLiteral.
|
||||
|
@ -1171,6 +1171,12 @@ TEST(TernaryBadCondition) {
|
||||
"asm: line 39: condition must be of type int\n");
|
||||
}
|
||||
|
||||
TEST(BadIntishMultiply) {
|
||||
CHECK_FUNC_ERROR(
|
||||
"function bar() { var x = 1; return ((x + x) * 4) | 0; }\n"
|
||||
"function foo() { bar(); }",
|
||||
"asm: line 39: intish not allowed in multiply\n");
|
||||
}
|
||||
|
||||
TEST(FroundFloat32) {
|
||||
CHECK_FUNC_TYPES_BEGIN(
|
||||
@ -1229,7 +1235,7 @@ TEST(Multiplication2) {
|
||||
CHECK_FUNC_ERROR(
|
||||
"function bar() { var x = 1; var y = 2; return (x*y)|0; }\n"
|
||||
"function foo() { bar(); }",
|
||||
"asm: line 39: direct integer multiply forbidden\n");
|
||||
"asm: line 39: multiply must be by an integer literal\n");
|
||||
}
|
||||
|
||||
|
||||
|
@ -1441,4 +1441,34 @@ TestForeignVariables();
|
||||
|
||||
var m = _WASMEXP_.instantiateModuleFromAsm(Module.toString());
|
||||
assertEquals(3, m.func());
|
||||
}) // TODO(bradnelson): Enable when Math.fround implementation lands.
|
||||
}); // TODO(bradnelson): Enable when Math.fround implementation lands.
|
||||
|
||||
|
||||
(function TestIntegerMultiplyBothWays() {
|
||||
function Module(stdlib, foreign, heap) {
|
||||
"use asm";
|
||||
function func() {
|
||||
var a = 1;
|
||||
return ((a * 3) + (4 * a)) | 0;
|
||||
}
|
||||
return {func: func};
|
||||
}
|
||||
|
||||
var m = _WASMEXP_.instantiateModuleFromAsm(Module.toString());
|
||||
assertEquals(7, m.func());
|
||||
})();
|
||||
|
||||
|
||||
(function TestBadMultiplyIntish() {
|
||||
function Module(stdlib, foreign, heap) {
|
||||
"use asm";
|
||||
function func() {
|
||||
var a = 1;
|
||||
return ((a + a) * 4) | 0;
|
||||
}
|
||||
return {func: func};
|
||||
}
|
||||
assertThrows(function() {
|
||||
_WASMEXP_.instantiateModuleFromAsm(Module.toString());
|
||||
});
|
||||
})();
|
||||
|
Loading…
Reference in New Issue
Block a user