Index: src/asmjs/asm-typer.cc |
diff --git a/src/asmjs/asm-typer.cc b/src/asmjs/asm-typer.cc |
index 95834f1d1c6bda82f6ca57e49281dae15bf29d18..6640bbab6b67fce0fc2b81f07a72e9f4ed980884 100644 |
--- a/src/asmjs/asm-typer.cc |
+++ b/src/asmjs/asm-typer.cc |
@@ -762,9 +762,15 @@ AsmType* AsmTyper::ValidateGlobalDeclaration(Assignment* assign) { |
bool global_variable = false; |
if (value->IsLiteral() || value->IsCall()) { |
AsmType* type = nullptr; |
- RECURSE(type = VariableTypeAnnotations(value, true)); |
+ VariableInfo::Mutability mutability; |
+ if (target_variable->mode() == CONST) { |
+ mutability = VariableInfo::kConstGlobal; |
+ } else { |
+ mutability = VariableInfo::kMutableGlobal; |
+ } |
+ RECURSE(type = VariableTypeAnnotations(value, mutability)); |
target_info = new (zone_) VariableInfo(type); |
- target_info->set_mutability(VariableInfo::kMutableGlobal); |
+ target_info->set_mutability(mutability); |
global_variable = true; |
} else if (value->IsProperty()) { |
target_info = ImportLookup(value->AsProperty()); |
@@ -828,6 +834,23 @@ AsmType* AsmTyper::ValidateGlobalDeclaration(Assignment* assign) { |
RECURSE(type = NewHeapView(value->AsCallNew())); |
target_info = new (zone_) VariableInfo(type); |
target_info->set_mutability(VariableInfo::kImmutableGlobal); |
+ } else if (auto* proxy = value->AsVariableProxy()) { |
+ auto* var_info = Lookup(proxy->var()); |
+ |
+ if (var_info == nullptr) { |
+ FAIL(value, "Undeclared identifier in global initializer"); |
+ } |
+ |
+ if (var_info->mutability() != VariableInfo::kConstGlobal) { |
+ FAIL(value, "Identifier used to initialize a global must be a const"); |
+ } |
+ |
+ target_info = new (zone_) VariableInfo(var_info->type()); |
+ if (target_variable->mode() == CONST) { |
+ target_info->set_mutability(VariableInfo::kConstGlobal); |
+ } else { |
+ target_info->set_mutability(VariableInfo::kMutableGlobal); |
+ } |
} |
if (target_info == nullptr) { |
@@ -2684,13 +2707,27 @@ AsmType* AsmTyper::ReturnTypeAnnotations(ReturnStatement* statement) { |
FAIL(statement, "Invalid literal in return statement."); |
} |
+ if (auto* proxy = ret_expr->AsVariableProxy()) { |
+ auto* var_info = Lookup(proxy->var()); |
+ |
+ if (var_info == nullptr) { |
+ FAIL(statement, "Undeclared identifier in return statement."); |
+ } |
+ |
+ if (var_info->mutability() != VariableInfo::kConstGlobal) { |
+ FAIL(statement, "Identifier in return statement is not const."); |
+ } |
+ |
+ return var_info->type(); |
+ } |
+ |
FAIL(statement, "Invalid return type expression."); |
} |
// 5.4 VariableTypeAnnotations |
// Also used for 5.5 GlobalVariableTypeAnnotations |
-AsmType* AsmTyper::VariableTypeAnnotations(Expression* initializer, |
- bool global) { |
+AsmType* AsmTyper::VariableTypeAnnotations( |
+ Expression* initializer, VariableInfo::Mutability mutability_type) { |
if (auto* literal = initializer->AsLiteral()) { |
if (literal->raw_value()->ContainsDot()) { |
SetTypeOf(initializer, AsmType::Double()); |
@@ -2698,24 +2735,50 @@ AsmType* AsmTyper::VariableTypeAnnotations(Expression* initializer, |
} |
int32_t i32; |
uint32_t u32; |
+ |
+ AsmType* initializer_type = nullptr; |
if (literal->value()->ToUint32(&u32)) { |
if (u32 > LargestFixNum) { |
- SetTypeOf(initializer, AsmType::Unsigned()); |
+ initializer_type = AsmType::Unsigned(); |
+ SetTypeOf(initializer, initializer_type); |
} else { |
- SetTypeOf(initializer, AsmType::FixNum()); |
+ initializer_type = AsmType::FixNum(); |
+ SetTypeOf(initializer, initializer_type); |
+ initializer_type = AsmType::Signed(); |
} |
} else if (literal->value()->ToInt32(&i32)) { |
- SetTypeOf(initializer, AsmType::Signed()); |
+ initializer_type = AsmType::Signed(); |
+ SetTypeOf(initializer, initializer_type); |
} else { |
FAIL(initializer, "Invalid type annotation - forbidden literal."); |
} |
- return AsmType::Int(); |
+ if (mutability_type != VariableInfo::kConstGlobal) { |
+ return AsmType::Int(); |
+ } |
+ return initializer_type; |
+ } |
+ |
+ if (auto* proxy = initializer->AsVariableProxy()) { |
+ auto* var_info = Lookup(proxy->var()); |
+ |
+ if (var_info == nullptr) { |
+ FAIL(initializer, |
+ "Undeclared identifier in variable declaration initializer."); |
+ } |
+ |
+ if (var_info->mutability() != VariableInfo::kConstGlobal) { |
+ FAIL(initializer, |
+ "Identifier in variable declaration initializer must be const."); |
+ } |
+ |
+ SetTypeOf(initializer, var_info->type()); |
+ return var_info->type(); |
} |
auto* call = initializer->AsCall(); |
if (call == nullptr) { |
FAIL(initializer, |
- "Invalid variable initialization - it should be a literal, or " |
+ "Invalid variable initialization - it should be a literal, const, or " |
"fround(literal)."); |
} |
@@ -2732,7 +2795,7 @@ AsmType* AsmTyper::VariableTypeAnnotations(Expression* initializer, |
} |
// Float constants must contain dots in local, but not in globals. |
- if (!global) { |
+ if (mutability_type == VariableInfo::kLocal) { |
if (!src_expr->raw_value()->ContainsDot()) { |
FAIL(initializer, |
"Invalid float type annotation - expected literal argument to be a " |