Commit be10e68f authored by bradnelson's avatar bradnelson Committed by Commit bot

Forbid non-locals/keyed-property calls to allow interleaved compile.

Deferred function call validation is required to support out of order
asm.js function declaration. Unfortunately, since we've started interleaving
validation and asm-wasm building, we don't check names are resolved until
the end.
Fortunately, undefined names can be detected from their CallType.
Check this at asm-typer time.

BUG=676797
R=aseemgarg@chromium.org,titzer@chromium.org

Review-Url: https://codereview.chromium.org/2615443003
Cr-Commit-Position: refs/heads/master@{#42158}
parent 0dde3045
...@@ -2389,6 +2389,9 @@ AsmType* AsmTyper::ValidateCall(AsmType* return_type, Call* call) { ...@@ -2389,6 +2389,9 @@ AsmType* AsmTyper::ValidateCall(AsmType* return_type, Call* call) {
DCHECK(false); DCHECK(false);
FAIL(call, "Redeclared global identifier."); FAIL(call, "Redeclared global identifier.");
} }
if (call->GetCallType() != Call::OTHER_CALL) {
FAIL(call, "Invalid call of existing global function.");
}
SetTypeOf(call_var_proxy, reinterpret_cast<AsmType*>(call_type)); SetTypeOf(call_var_proxy, reinterpret_cast<AsmType*>(call_type));
SetTypeOf(call, return_type); SetTypeOf(call, return_type);
return return_type; return return_type;
...@@ -2419,6 +2422,10 @@ AsmType* AsmTyper::ValidateCall(AsmType* return_type, Call* call) { ...@@ -2419,6 +2422,10 @@ AsmType* AsmTyper::ValidateCall(AsmType* return_type, Call* call) {
FAIL(call, "Function invocation does not match function type."); FAIL(call, "Function invocation does not match function type.");
} }
if (call->GetCallType() != Call::OTHER_CALL) {
FAIL(call, "Invalid forward call of global function.");
}
SetTypeOf(call_var_proxy, call_var_info->type()); SetTypeOf(call_var_proxy, call_var_info->type());
SetTypeOf(call, return_type); SetTypeOf(call, return_type);
return return_type; return return_type;
...@@ -2477,6 +2484,9 @@ AsmType* AsmTyper::ValidateCall(AsmType* return_type, Call* call) { ...@@ -2477,6 +2484,9 @@ AsmType* AsmTyper::ValidateCall(AsmType* return_type, Call* call) {
DCHECK(false); DCHECK(false);
FAIL(call, "Redeclared global identifier."); FAIL(call, "Redeclared global identifier.");
} }
if (call->GetCallType() != Call::KEYED_PROPERTY_CALL) {
FAIL(call, "Invalid call of existing function table.");
}
SetTypeOf(call_property, reinterpret_cast<AsmType*>(call_type)); SetTypeOf(call_property, reinterpret_cast<AsmType*>(call_type));
SetTypeOf(call, return_type); SetTypeOf(call, return_type);
return return_type; return return_type;
...@@ -2501,6 +2511,9 @@ AsmType* AsmTyper::ValidateCall(AsmType* return_type, Call* call) { ...@@ -2501,6 +2511,9 @@ AsmType* AsmTyper::ValidateCall(AsmType* return_type, Call* call) {
"signature."); "signature.");
} }
if (call->GetCallType() != Call::KEYED_PROPERTY_CALL) {
FAIL(call, "Invalid forward call of function table.");
}
SetTypeOf(call_property, previous_type->signature()); SetTypeOf(call_property, previous_type->signature());
SetTypeOf(call, return_type); SetTypeOf(call, return_type);
return return_type; return return_type;
......
...@@ -100,6 +100,9 @@ class AsmTyperHarnessBuilder { ...@@ -100,6 +100,9 @@ class AsmTyperHarnessBuilder {
CHECK(validation_type_ == ValidateStatement || CHECK(validation_type_ == ValidateStatement ||
validation_type_ == ValidateExpression); validation_type_ == ValidateExpression);
auto* var = DeclareVariable(var_name); auto* var = DeclareVariable(var_name);
if (var->IsUnallocated()) {
var->AllocateTo(VariableLocation::LOCAL, -1);
}
auto* var_info = new (zone_) AsmTyper::VariableInfo(type); auto* var_info = new (zone_) AsmTyper::VariableInfo(type);
var_info->set_mutability(AsmTyper::VariableInfo::kLocal); var_info->set_mutability(AsmTyper::VariableInfo::kLocal);
CHECK(typer_->AddLocal(var, var_info)); CHECK(typer_->AddLocal(var, var_info));
...@@ -108,9 +111,14 @@ class AsmTyperHarnessBuilder { ...@@ -108,9 +111,14 @@ class AsmTyperHarnessBuilder {
AsmTyperHarnessBuilder* WithGlobal(VariableName var_name, AsmType* type) { AsmTyperHarnessBuilder* WithGlobal(VariableName var_name, AsmType* type) {
auto* var = DeclareVariable(var_name); auto* var = DeclareVariable(var_name);
if (var->IsUnallocated()) {
var->AllocateTo(VariableLocation::MODULE, -1);
}
if (type != nullptr) {
auto* var_info = new (zone_) AsmTyper::VariableInfo(type); auto* var_info = new (zone_) AsmTyper::VariableInfo(type);
var_info->set_mutability(AsmTyper::VariableInfo::kMutableGlobal); var_info->set_mutability(AsmTyper::VariableInfo::kMutableGlobal);
CHECK(typer_->AddGlobal(var, var_info)); CHECK(typer_->AddGlobal(var, var_info));
}
return this; return this;
} }
...@@ -135,6 +143,9 @@ class AsmTyperHarnessBuilder { ...@@ -135,6 +143,9 @@ class AsmTyperHarnessBuilder {
AsmTyperHarnessBuilder* WithImport(VariableName var_name, AsmTyperHarnessBuilder* WithImport(VariableName var_name,
AsmTyper::StandardMember standard_member) { AsmTyper::StandardMember standard_member) {
auto* var = DeclareVariable(var_name); auto* var = DeclareVariable(var_name);
if (var->IsUnallocated()) {
var->AllocateTo(VariableLocation::LOCAL, -1);
}
AsmTyper::VariableInfo* var_info = nullptr; AsmTyper::VariableInfo* var_info = nullptr;
auto* stdlib_map = &typer_->stdlib_math_types_; auto* stdlib_map = &typer_->stdlib_math_types_;
switch (standard_member) { switch (standard_member) {
...@@ -219,7 +230,9 @@ class AsmTyperHarnessBuilder { ...@@ -219,7 +230,9 @@ class AsmTyperHarnessBuilder {
return true; return true;
} }
std::cerr << "Asm validation failed: " << typer_->error_message() << "\n"; std::unique_ptr<char[]> msg = i::MessageHandler::GetLocalizedMessage(
isolate_, typer_->error_message());
std::cerr << "Asm validation failed: " << msg.get() << "\n";
return false; return false;
} }
...@@ -227,7 +240,9 @@ class AsmTyperHarnessBuilder { ...@@ -227,7 +240,9 @@ class AsmTyperHarnessBuilder {
CHECK(validation_type_ == ValidateExpression); CHECK(validation_type_ == ValidateExpression);
auto* validated_as = ValidateExpressionStatment(fun_decl_); auto* validated_as = ValidateExpressionStatment(fun_decl_);
if (validated_as == AsmType::None()) { if (validated_as == AsmType::None()) {
std::cerr << "Validation failure: " << typer_->error_message() << "\n"; std::unique_ptr<char[]> msg = i::MessageHandler::GetLocalizedMessage(
isolate_, typer_->error_message());
std::cerr << "Validation failure: " << msg.get() << "\n";
return false; return false;
} else if (validated_as != type) { } else if (validated_as != type) {
std::cerr << "Validation succeeded with wrong type " std::cerr << "Validation succeeded with wrong type "
...@@ -675,7 +690,8 @@ TEST(ErrorsInModuleExport) { ...@@ -675,7 +690,8 @@ TEST(ErrorsInModuleExport) {
{"return {'a': ffi}", "cannot export foreign functions"}, {"return {'a': ffi}", "cannot export foreign functions"},
{"return {'a': f()}", "must be an asm.js function name"}, {"return {'a': f()}", "must be an asm.js function name"},
{"return {'a': f}", "Undefined identifier in asm.js module export"}, {"return {'a': f}", "Undefined identifier in asm.js module export"},
{"function v() { a(); } return {b: d2s}", "Missing definition for forw"}, {"function v() { a(); } return {b: d2s}",
"Invalid call of existing global function"},
{"function v() {} return {b: v, 'a': d2s_tbl}", {"function v() {} return {b: v, 'a': d2s_tbl}",
"cannot export function tables"}, "cannot export function tables"},
{"function v() {} return {b: v, 'a': min}", {"function v() {} return {b: v, 'a': min}",
...@@ -912,6 +928,7 @@ TEST(ErrorsInStatement) { ...@@ -912,6 +928,7 @@ TEST(ErrorsInStatement) {
->WithImport(DynamicGlobal("fround"), iw::AsmTyper::kMathFround) ->WithImport(DynamicGlobal("fround"), iw::AsmTyper::kMathFround)
->WithLocal(DynamicGlobal("flocal"), iw::AsmType::Float()) ->WithLocal(DynamicGlobal("flocal"), iw::AsmType::Float())
->WithLocal(DynamicGlobal("slocal"), iw::AsmType::Signed()) ->WithLocal(DynamicGlobal("slocal"), iw::AsmType::Signed())
->WithGlobal(DynamicGlobal("d"), nullptr)
->FailsWithMessage(test->error_message)) { ->FailsWithMessage(test->error_message)) {
std::cerr << "Test:\n" << test->statement; std::cerr << "Test:\n" << test->statement;
CHECK(false); CHECK(false);
...@@ -1042,6 +1059,7 @@ TEST(ErrorsInExpression) { ...@@ -1042,6 +1059,7 @@ TEST(ErrorsInExpression) {
->WithGlobal(DynamicGlobal("d2s_tbl"), d2s_tbl) ->WithGlobal(DynamicGlobal("d2s_tbl"), d2s_tbl)
->WithGlobal(DynamicGlobal("HEAP32"), iw::AsmType::Int32Array()) ->WithGlobal(DynamicGlobal("HEAP32"), iw::AsmType::Int32Array())
->WithGlobal(DynamicGlobal("HEAP8"), iw::AsmType::Int8Array()) ->WithGlobal(DynamicGlobal("HEAP8"), iw::AsmType::Int8Array())
->WithGlobal(DynamicGlobal("a"), nullptr)
->FailsWithMessage(test->error_message)) { ->FailsWithMessage(test->error_message)) {
std::cerr << "Test:\n" << test->expression; std::cerr << "Test:\n" << test->expression;
CHECK(false); CHECK(false);
...@@ -1369,6 +1387,8 @@ TEST(ValidateAssignmentExpression) { ...@@ -1369,6 +1387,8 @@ TEST(ValidateAssignmentExpression) {
->WithGlobal(DynamicGlobal("U32"), iw::AsmType::Uint32Array()) ->WithGlobal(DynamicGlobal("U32"), iw::AsmType::Uint32Array())
->WithGlobal(DynamicGlobal("F32"), iw::AsmType::Float32Array()) ->WithGlobal(DynamicGlobal("F32"), iw::AsmType::Float32Array())
->WithGlobal(DynamicGlobal("F64"), iw::AsmType::Float64Array()) ->WithGlobal(DynamicGlobal("F64"), iw::AsmType::Float64Array())
->WithGlobal(DynamicGlobal("make_float"), nullptr)
->WithGlobal(DynamicGlobal("make_double"), nullptr)
->SucceedsWithExactType(test->load_type)) { ->SucceedsWithExactType(test->load_type)) {
std::cerr << "Test:\n" << test->expression; std::cerr << "Test:\n" << test->expression;
CHECK(false); CHECK(false);
...@@ -1424,6 +1444,7 @@ TEST(ValidateUnaryExpression) { ...@@ -1424,6 +1444,7 @@ TEST(ValidateUnaryExpression) {
->WithLocal(DynamicGlobal("ulocal"), iw::AsmType::Unsigned()) ->WithLocal(DynamicGlobal("ulocal"), iw::AsmType::Unsigned())
->WithLocal(DynamicGlobal("ilocal"), iw::AsmType::Int()) ->WithLocal(DynamicGlobal("ilocal"), iw::AsmType::Int())
->WithGlobal(DynamicGlobal("dglobal"), iw::AsmType::Double()) ->WithGlobal(DynamicGlobal("dglobal"), iw::AsmType::Double())
->WithGlobal(DynamicGlobal("make_double"), nullptr)
->WithGlobal(DynamicGlobal("dbl"), v2d) ->WithGlobal(DynamicGlobal("dbl"), v2d)
->SucceedsWithExactType(test->load_type)) { ->SucceedsWithExactType(test->load_type)) {
std::cerr << "Test:\n" << test->expression; std::cerr << "Test:\n" << test->expression;
...@@ -1673,6 +1694,7 @@ TEST(ValidateBitwiseExpression) { ...@@ -1673,6 +1694,7 @@ TEST(ValidateBitwiseExpression) {
->WithLocal(DynamicGlobal("iish1"), iw::AsmType::Intish()) ->WithLocal(DynamicGlobal("iish1"), iw::AsmType::Intish())
->WithLocal(DynamicGlobal("iish0"), iw::AsmType::Intish()) ->WithLocal(DynamicGlobal("iish0"), iw::AsmType::Intish())
->WithGlobal(DynamicGlobal("signed"), v2s) ->WithGlobal(DynamicGlobal("signed"), v2s)
->WithGlobal(DynamicGlobal("make_signed"), nullptr)
->SucceedsWithExactType(test->load_type)) { ->SucceedsWithExactType(test->load_type)) {
std::cerr << "Test:\n" << test->expression; std::cerr << "Test:\n" << test->expression;
CHECK(false); CHECK(false);
...@@ -1720,7 +1742,7 @@ TEST(ValidateCall) { ...@@ -1720,7 +1742,7 @@ TEST(ValidateCall) {
// //
// ifd2_(&iw::AsmType::Float) // ifd2_(&iw::AsmType::Float)
// //
// returns an AsmType representing an asm.j function with the following // returns an AsmType representing an asm.js function with the following
// signature: // signature:
// //
// float(int, float, double) // float(int, float, double)
...@@ -1797,6 +1819,9 @@ TEST(ValidateCall) { ...@@ -1797,6 +1819,9 @@ TEST(ValidateCall) {
->WithLocal(DynamicGlobal("u"), iw::AsmType::Unsigned()) ->WithLocal(DynamicGlobal("u"), iw::AsmType::Unsigned())
->WithLocal(DynamicGlobal("iish"), iw::AsmType::Intish()) ->WithLocal(DynamicGlobal("iish"), iw::AsmType::Intish())
->WithGlobal(DynamicGlobal("v2f"), v2f) ->WithGlobal(DynamicGlobal("v2f"), v2f)
->WithGlobal(DynamicGlobal("ifd2f"), nullptr)
->WithGlobal(DynamicGlobal("ifd2d"), nullptr)
->WithGlobal(DynamicGlobal("ifd2i"), nullptr)
->WithGlobal(DynamicGlobal("ifd2f_tbl"), ifd2f_tbl) ->WithGlobal(DynamicGlobal("ifd2f_tbl"), ifd2f_tbl)
->WithGlobal(DynamicGlobal("ifd2d_tbl"), ifd2d_tbl) ->WithGlobal(DynamicGlobal("ifd2d_tbl"), ifd2d_tbl)
->WithGlobal(DynamicGlobal("ifd2i_tbl"), ifd2i_tbl) ->WithGlobal(DynamicGlobal("ifd2i_tbl"), ifd2i_tbl)
......
...@@ -401,3 +401,15 @@ function assertValidAsm(func) { ...@@ -401,3 +401,15 @@ function assertValidAsm(func) {
Module(); Module();
assertFalse(%IsAsmWasmCode(Module)); assertFalse(%IsAsmWasmCode(Module));
})(); })();
(function TestUndefinedGlobalCall() {
function Module() {
"use asm";
function foo() {
return bar() | 0;
}
return foo;
}
Module();
assertFalse(%IsAsmWasmCode(Module));
})();
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment