| Index: src/asmjs/asm-parser.cc
|
| diff --git a/src/asmjs/asm-parser.cc b/src/asmjs/asm-parser.cc
|
| index 59745c191de58d175f74820421d266403568142e..d3c6f1a18a36ac96d4e0ebd36eb3c79fa3b1872a 100644
|
| --- a/src/asmjs/asm-parser.cc
|
| +++ b/src/asmjs/asm-parser.cc
|
| @@ -71,12 +71,11 @@ namespace wasm {
|
|
|
| #define RECURSE_OR_RETURN(ret, call) \
|
| do { \
|
| - DCHECK(GetCurrentStackPosition() >= stack_limit_); \
|
| DCHECK(!failed_); \
|
| - call; \
|
| if (GetCurrentStackPosition() < stack_limit_) { \
|
| FAIL_AND_RETURN(ret, "Stack overflow while parsing asm.js module."); \
|
| } \
|
| + call; \
|
| if (failed_) return ret; \
|
| } while (false);
|
|
|
| @@ -238,21 +237,25 @@ uint32_t AsmJsParser::VarIndex(VarInfo* info) {
|
| void AsmJsParser::AddGlobalImport(std::string name, AsmType* type,
|
| ValueType vtype, bool mutable_variable,
|
| VarInfo* info) {
|
| + // TODO(bradnelson): Refactor memory management here.
|
| + // AsmModuleBuilder should really own import names.
|
| + char* name_data = zone()->NewArray<char>(name.size());
|
| + memcpy(name_data, name.data(), name.size());
|
| if (mutable_variable) {
|
| // Allocate a separate variable for the import.
|
| DeclareGlobal(info, true, type, vtype);
|
| // Record the need to initialize the global from the import.
|
| - global_imports_.push_back({name, 0, info->index, true});
|
| + global_imports_.push_back({name_data, name.size(), 0, info->index, true});
|
| } else {
|
| // Just use the import directly.
|
| - global_imports_.push_back({name, 0, info->index, false});
|
| + global_imports_.push_back({name_data, name.size(), 0, info->index, false});
|
| }
|
| GlobalImport& gi = global_imports_.back();
|
| // TODO(bradnelson): Reuse parse buffer memory / make wasm-module-builder
|
| // managed the memory for the import name (currently have to keep our
|
| // own memory for it).
|
| gi.import_index = module_builder_->AddGlobalImport(
|
| - name.data(), static_cast<int>(name.size()), vtype);
|
| + name_data, static_cast<int>(name.size()), vtype);
|
| if (!mutable_variable) {
|
| info->DeclareGlobalImport(type, gi.import_index);
|
| }
|
| @@ -362,6 +365,16 @@ void AsmJsParser::ValidateModule() {
|
| }
|
| RECURSE(ValidateExport());
|
|
|
| + // Check that all functions were eventually defined.
|
| + for (auto info : global_var_info_) {
|
| + if (info.kind != VarKind::kFunction) {
|
| + continue;
|
| + }
|
| + if (!info.function_defined) {
|
| + FAIL("Undefined function");
|
| + }
|
| + }
|
| +
|
| // Add start function to init things.
|
| WasmFunctionBuilder* start = module_builder_->AddFunction();
|
| module_builder_->MarkStartFunction(start);
|
| @@ -447,8 +460,9 @@ void AsmJsParser::ValidateModuleVar(bool mutable_variable) {
|
| if (uvalue > 0x7fffffff) {
|
| FAIL("Numeric literal out of range");
|
| }
|
| - DeclareGlobal(info, mutable_variable, AsmType::Int(), kWasmI32,
|
| - WasmInitExpr(static_cast<int32_t>(uvalue)));
|
| + DeclareGlobal(info, mutable_variable,
|
| + mutable_variable ? AsmType::Int() : AsmType::Signed(),
|
| + kWasmI32, WasmInitExpr(static_cast<int32_t>(uvalue)));
|
| } else if (Check('-')) {
|
| if (CheckForDouble(&dvalue)) {
|
| DeclareGlobal(info, mutable_variable, AsmType::Double(), kWasmF64,
|
| @@ -457,8 +471,9 @@ void AsmJsParser::ValidateModuleVar(bool mutable_variable) {
|
| if (uvalue > 0x7fffffff) {
|
| FAIL("Numeric literal out of range");
|
| }
|
| - DeclareGlobal(info, mutable_variable, AsmType::Int(), kWasmI32,
|
| - WasmInitExpr(-static_cast<int32_t>(uvalue)));
|
| + DeclareGlobal(info, mutable_variable,
|
| + mutable_variable ? AsmType::Int() : AsmType::Signed(),
|
| + kWasmI32, WasmInitExpr(-static_cast<int32_t>(uvalue)));
|
| } else {
|
| FAIL("Expected numeric literal");
|
| }
|
| @@ -470,16 +485,33 @@ void AsmJsParser::ValidateModuleVar(bool mutable_variable) {
|
| } else if (ValidateModuleVarImport(info, mutable_variable)) {
|
| // Handled inside.
|
| } else if (scanner_.IsGlobal()) {
|
| - RECURSE(ValidateModuleVarFloat(info, mutable_variable));
|
| + RECURSE(ValidateModuleVarFromGlobal(info, mutable_variable));
|
| } else {
|
| FAIL("Bad variable declaration");
|
| }
|
| }
|
|
|
| // 6.1 ValidateModule - global float declaration
|
| -void AsmJsParser::ValidateModuleVarFloat(VarInfo* info, bool mutable_variable) {
|
| - if (!GetVarInfo(Consume())->type->IsA(stdlib_fround_)) {
|
| - FAIL("Expected fround");
|
| +void AsmJsParser::ValidateModuleVarFromGlobal(VarInfo* info,
|
| + bool mutable_variable) {
|
| + VarInfo* src_info = GetVarInfo(Consume());
|
| + if (!src_info->type->IsA(stdlib_fround_)) {
|
| + if (src_info->mutable_variable) {
|
| + FAIL("Can only use immutable variables in global definition");
|
| + }
|
| + if (mutable_variable) {
|
| + FAIL("Can only define immutable variables with other immutables");
|
| + }
|
| + if (!src_info->type->IsA(AsmType::Int()) &&
|
| + !src_info->type->IsA(AsmType::Float()) &&
|
| + !src_info->type->IsA(AsmType::Double())) {
|
| + FAIL("Expected int, float, double, or fround for global definition");
|
| + }
|
| + info->kind = VarKind::kGlobal;
|
| + info->type = src_info->type;
|
| + info->index = src_info->index;
|
| + info->mutable_variable = false;
|
| + return;
|
| }
|
| EXPECT_TOKEN('(');
|
| bool negate = false;
|
| @@ -532,7 +564,11 @@ bool AsmJsParser::ValidateModuleVarImport(VarInfo* info,
|
| info->kind = VarKind::kImportedFunction;
|
| function_import_info_.resize(function_import_info_.size() + 1);
|
| info->import = &function_import_info_.back();
|
| - info->import->name = import_name;
|
| + // TODO(bradnelson): Refactor memory management here.
|
| + // AsmModuleBuilder should really own import names.
|
| + info->import->function_name = zone()->NewArray<char>(import_name.size());
|
| + memcpy(info->import->function_name, import_name.data(), import_name.size());
|
| + info->import->function_name_size = import_name.size();
|
| return true;
|
| }
|
| return false;
|
| @@ -569,6 +605,7 @@ void AsmJsParser::ValidateModuleVarStdlib(VarInfo* info) {
|
| case TOK(name): \
|
| DeclareGlobal(info, false, AsmType::Double(), kWasmF64, \
|
| WasmInitExpr(M_##name)); \
|
| + stdlib_uses_.insert(AsmTyper::kMath##name); \
|
| break;
|
| STDLIB_MATH_VALUE_LIST(V)
|
| #undef V
|
| @@ -585,9 +622,11 @@ void AsmJsParser::ValidateModuleVarStdlib(VarInfo* info) {
|
| } else if (Check(TOK(Infinity))) {
|
| DeclareGlobal(info, false, AsmType::Double(), kWasmF64,
|
| WasmInitExpr(std::numeric_limits<double>::infinity()));
|
| + stdlib_uses_.insert(AsmTyper::kInfinity);
|
| } else if (Check(TOK(NaN))) {
|
| DeclareGlobal(info, false, AsmType::Double(), kWasmF64,
|
| WasmInitExpr(std::numeric_limits<double>::quiet_NaN()));
|
| + stdlib_uses_.insert(AsmTyper::kNaN);
|
| } else {
|
| FAIL("Invalid member of stdlib");
|
| }
|
| @@ -695,13 +734,18 @@ void AsmJsParser::ValidateFunction() {
|
| if (function_info->kind == VarKind::kUnused) {
|
| function_info->kind = VarKind::kFunction;
|
| function_info->function_builder = module_builder_->AddFunction();
|
| + // TODO(bradnelson): Cleanup memory management here.
|
| + // WasmModuleBuilder should own these.
|
| + char* function_name = zone()->NewArray<char>(function_name_raw.size());
|
| + memcpy(function_name, function_name_raw.data(), function_name_raw.size());
|
| function_info->function_builder->SetName(
|
| - {function_name_raw.c_str(),
|
| - static_cast<int>(function_name_raw.size())});
|
| + {function_name, static_cast<int>(function_name_raw.size())});
|
| function_info->index = function_info->function_builder->func_index();
|
| function_info->function_defined = true;
|
| } else if (function_info->function_defined) {
|
| FAIL("Function redefined");
|
| + } else {
|
| + function_info->function_defined = true;
|
| }
|
| current_function_builder_ = function_info->function_builder;
|
| return_type_ = nullptr;
|
| @@ -855,7 +899,7 @@ void AsmJsParser::ValidateFunctionLocals(
|
| info->type = AsmType::Double();
|
| info->index = static_cast<uint32_t>(param_count + locals->size());
|
| locals->push_back(kWasmF64);
|
| - byte code[] = {WASM_F64(dvalue)};
|
| + byte code[] = {WASM_F64(-dvalue)};
|
| current_function_builder_->EmitCode(code, sizeof(code));
|
| current_function_builder_->EmitSetLocal(info->index);
|
| } else if (CheckForUnsigned(&uvalue)) {
|
| @@ -2063,8 +2107,9 @@ AsmType* AsmJsParser::ValidateCall() {
|
| uint32_t index;
|
| if (cache_index >= function_info->import->cache_index.size()) {
|
| index = module_builder_->AddImport(
|
| - function_info->import->name.data(),
|
| - static_cast<uint32_t>(function_info->import->name.size()), sig);
|
| + function_info->import->function_name,
|
| + static_cast<uint32_t>(function_info->import->function_name_size),
|
| + sig);
|
| function_info->import->cache_index.push_back(index);
|
| } else {
|
| index = function_info->import->cache_index[cache_index];
|
|
|