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) {
DCHECK(false);
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, return_type);
return return_type;
......@@ -2419,6 +2422,10 @@ AsmType* AsmTyper::ValidateCall(AsmType* return_type, Call* call) {
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, return_type);
return return_type;
......@@ -2477,6 +2484,9 @@ AsmType* AsmTyper::ValidateCall(AsmType* return_type, Call* call) {
DCHECK(false);
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, return_type);
return return_type;
......@@ -2501,6 +2511,9 @@ AsmType* AsmTyper::ValidateCall(AsmType* return_type, Call* call) {
"signature.");
}
if (call->GetCallType() != Call::KEYED_PROPERTY_CALL) {
FAIL(call, "Invalid forward call of function table.");
}
SetTypeOf(call_property, previous_type->signature());
SetTypeOf(call, return_type);
return return_type;
......
......@@ -100,6 +100,9 @@ class AsmTyperHarnessBuilder {
CHECK(validation_type_ == ValidateStatement ||
validation_type_ == ValidateExpression);
auto* var = DeclareVariable(var_name);
if (var->IsUnallocated()) {
var->AllocateTo(VariableLocation::LOCAL, -1);
}
auto* var_info = new (zone_) AsmTyper::VariableInfo(type);
var_info->set_mutability(AsmTyper::VariableInfo::kLocal);
CHECK(typer_->AddLocal(var, var_info));
......@@ -108,9 +111,14 @@ class AsmTyperHarnessBuilder {
AsmTyperHarnessBuilder* WithGlobal(VariableName var_name, AsmType* type) {
auto* var = DeclareVariable(var_name);
if (var->IsUnallocated()) {
var->AllocateTo(VariableLocation::MODULE, -1);
}
if (type != nullptr) {
auto* var_info = new (zone_) AsmTyper::VariableInfo(type);
var_info->set_mutability(AsmTyper::VariableInfo::kMutableGlobal);
CHECK(typer_->AddGlobal(var, var_info));
}
return this;
}
......@@ -135,6 +143,9 @@ class AsmTyperHarnessBuilder {
AsmTyperHarnessBuilder* WithImport(VariableName var_name,
AsmTyper::StandardMember standard_member) {
auto* var = DeclareVariable(var_name);
if (var->IsUnallocated()) {
var->AllocateTo(VariableLocation::LOCAL, -1);
}
AsmTyper::VariableInfo* var_info = nullptr;
auto* stdlib_map = &typer_->stdlib_math_types_;
switch (standard_member) {
......@@ -219,7 +230,9 @@ class AsmTyperHarnessBuilder {
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;
}
......@@ -227,7 +240,9 @@ class AsmTyperHarnessBuilder {
CHECK(validation_type_ == ValidateExpression);
auto* validated_as = ValidateExpressionStatment(fun_decl_);
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;
} else if (validated_as != type) {
std::cerr << "Validation succeeded with wrong type "
......@@ -675,7 +690,8 @@ TEST(ErrorsInModuleExport) {
{"return {'a': ffi}", "cannot export foreign functions"},
{"return {'a': f()}", "must be an asm.js function name"},
{"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}",
"cannot export function tables"},
{"function v() {} return {b: v, 'a': min}",
......@@ -912,6 +928,7 @@ TEST(ErrorsInStatement) {
->WithImport(DynamicGlobal("fround"), iw::AsmTyper::kMathFround)
->WithLocal(DynamicGlobal("flocal"), iw::AsmType::Float())
->WithLocal(DynamicGlobal("slocal"), iw::AsmType::Signed())
->WithGlobal(DynamicGlobal("d"), nullptr)
->FailsWithMessage(test->error_message)) {
std::cerr << "Test:\n" << test->statement;
CHECK(false);
......@@ -1042,6 +1059,7 @@ TEST(ErrorsInExpression) {
->WithGlobal(DynamicGlobal("d2s_tbl"), d2s_tbl)
->WithGlobal(DynamicGlobal("HEAP32"), iw::AsmType::Int32Array())
->WithGlobal(DynamicGlobal("HEAP8"), iw::AsmType::Int8Array())
->WithGlobal(DynamicGlobal("a"), nullptr)
->FailsWithMessage(test->error_message)) {
std::cerr << "Test:\n" << test->expression;
CHECK(false);
......@@ -1369,6 +1387,8 @@ TEST(ValidateAssignmentExpression) {
->WithGlobal(DynamicGlobal("U32"), iw::AsmType::Uint32Array())
->WithGlobal(DynamicGlobal("F32"), iw::AsmType::Float32Array())
->WithGlobal(DynamicGlobal("F64"), iw::AsmType::Float64Array())
->WithGlobal(DynamicGlobal("make_float"), nullptr)
->WithGlobal(DynamicGlobal("make_double"), nullptr)
->SucceedsWithExactType(test->load_type)) {
std::cerr << "Test:\n" << test->expression;
CHECK(false);
......@@ -1424,6 +1444,7 @@ TEST(ValidateUnaryExpression) {
->WithLocal(DynamicGlobal("ulocal"), iw::AsmType::Unsigned())
->WithLocal(DynamicGlobal("ilocal"), iw::AsmType::Int())
->WithGlobal(DynamicGlobal("dglobal"), iw::AsmType::Double())
->WithGlobal(DynamicGlobal("make_double"), nullptr)
->WithGlobal(DynamicGlobal("dbl"), v2d)
->SucceedsWithExactType(test->load_type)) {
std::cerr << "Test:\n" << test->expression;
......@@ -1673,6 +1694,7 @@ TEST(ValidateBitwiseExpression) {
->WithLocal(DynamicGlobal("iish1"), iw::AsmType::Intish())
->WithLocal(DynamicGlobal("iish0"), iw::AsmType::Intish())
->WithGlobal(DynamicGlobal("signed"), v2s)
->WithGlobal(DynamicGlobal("make_signed"), nullptr)
->SucceedsWithExactType(test->load_type)) {
std::cerr << "Test:\n" << test->expression;
CHECK(false);
......@@ -1720,7 +1742,7 @@ TEST(ValidateCall) {
//
// 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:
//
// float(int, float, double)
......@@ -1797,6 +1819,9 @@ TEST(ValidateCall) {
->WithLocal(DynamicGlobal("u"), iw::AsmType::Unsigned())
->WithLocal(DynamicGlobal("iish"), iw::AsmType::Intish())
->WithGlobal(DynamicGlobal("v2f"), v2f)
->WithGlobal(DynamicGlobal("ifd2f"), nullptr)
->WithGlobal(DynamicGlobal("ifd2d"), nullptr)
->WithGlobal(DynamicGlobal("ifd2i"), nullptr)
->WithGlobal(DynamicGlobal("ifd2f_tbl"), ifd2f_tbl)
->WithGlobal(DynamicGlobal("ifd2d_tbl"), ifd2d_tbl)
->WithGlobal(DynamicGlobal("ifd2i_tbl"), ifd2i_tbl)
......
......@@ -401,3 +401,15 @@ function assertValidAsm(func) {
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