Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(1867)

Unified Diff: src/asmjs/asm-typer.cc

Issue 2134333003: V8. ASM-2-WASM. Migrates asm-wasm-builder to the new asm-typer. (Closed) Base URL: https://chromium.googlesource.com/v8/v8.git@master
Patch Set: addresses comments. Created 4 years, 5 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View side-by-side diff with in-line comments
Download patch
« no previous file with comments | « src/asmjs/asm-typer.h ('k') | src/asmjs/asm-types.h » ('j') | no next file with comments »
Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
Index: src/asmjs/asm-typer.cc
diff --git a/src/asmjs/asm-typer.cc b/src/asmjs/asm-typer.cc
index 07bf63fd0214373df57bfaf92f122bef5766ea59..9bc19f2aebce2890c899c0f245cc7e8e9759ba3e 100644
--- a/src/asmjs/asm-typer.cc
+++ b/src/asmjs/asm-typer.cc
@@ -48,6 +48,9 @@
namespace v8 {
namespace internal {
namespace wasm {
+namespace {
+static const uint32_t LargestFixNum = std::numeric_limits<int32_t>::max();
+} // namespace
using v8::internal::AstNode;
using v8::internal::GetCurrentStackPosition;
@@ -122,7 +125,8 @@ AsmTyper::AsmTyper(Isolate* isolate, Zone* zone, Script* script,
ZoneHashMap::kDefaultHashMapCapacity,
ZoneAllocationPolicy(zone)),
stack_limit_(isolate->stack_guard()->real_climit()),
- node_types_(zone_) {
+ node_types_(zone_),
+ fround_type_(AsmType::FroundType(zone_)) {
InitializeStdlib();
module_info_.set_standard_member(kModule);
}
@@ -165,12 +169,16 @@ void AsmTyper::InitializeStdlib() {
ii2s->AsFunctionType()->AddArgument(i);
auto* minmax_d = AsmType::MinMaxType(zone_, d, d);
+ // *VIOLATION* The float variant is not part of the spec, but firefox accepts
+ // it.
+ auto* minmax_f = AsmType::MinMaxType(zone_, f, f);
auto* minmax_i = AsmType::MinMaxType(zone_, s, i);
auto* minmax = AsmType::OverloadedFunction(zone_);
minmax->AsOverloadedFunctionType()->AddOverload(minmax_i);
+ minmax->AsOverloadedFunctionType()->AddOverload(minmax_f);
minmax->AsOverloadedFunctionType()->AddOverload(minmax_d);
- auto* fround = AsmType::FroundType(zone_);
+ auto* fround = fround_type_;
auto* abs = AsmType::OverloadedFunction(zone_);
abs->AsOverloadedFunctionType()->AddOverload(s2s);
@@ -362,17 +370,36 @@ bool AsmTyper::AddLocal(Variable* variable, VariableInfo* info) {
void AsmTyper::SetTypeOf(AstNode* node, AsmType* type) {
DCHECK_NE(type, AsmType::None());
- auto** node_type = &node_types_[node];
- DCHECK(*node_type == nullptr);
- *node_type = type;
+ DCHECK(node_types_.find(node) == node_types_.end());
+ node_types_.insert(std::make_pair(node, type));
}
AsmType* AsmTyper::TypeOf(AstNode* node) const {
auto node_type_iter = node_types_.find(node);
- if (node_type_iter == node_types_.end()) {
- return AsmType::None();
+ if (node_type_iter != node_types_.end()) {
+ return node_type_iter->second;
+ }
+
+ // Sometimes literal nodes are not added to the node_type_ map simply because
+ // their are not visited with ValidateExpression().
+ if (auto* literal = node->AsLiteral()) {
+ if (literal->raw_value()->ContainsDot()) {
+ return AsmType::Double();
+ }
+ uint32_t u;
+ if (literal->value()->ToUint32(&u)) {
+ if (u > LargestFixNum) {
+ return AsmType::Unsigned();
+ }
+ return AsmType::FixNum();
+ }
+ int32_t i;
+ if (literal->value()->ToInt32(&i)) {
+ return AsmType::Signed();
+ }
}
- return node_type_iter->second;
+
+ return AsmType::None();
}
AsmTyper::StandardMember AsmTyper::VariableAsStandardMember(Variable* var) {
@@ -607,11 +634,13 @@ AsmType* AsmTyper::ValidateGlobalDeclaration(Assignment* assign) {
auto* value = assign->value();
// Not all types of assignment are allowed by asm.js. See
// 5.5 Global Variable Type Annotations.
+ bool global_variable = false;
if (value->IsLiteral() || value->IsCall()) {
AsmType* type = nullptr;
RECURSE(type = VariableTypeAnnotations(value));
target_info = new (zone_) VariableInfo(type);
target_info->set_mutability(VariableInfo::kMutableGlobal);
+ global_variable = true;
} else if (value->IsProperty()) {
target_info = ImportLookup(value->AsProperty());
if (target_info == nullptr) {
@@ -689,6 +718,12 @@ AsmType* AsmTyper::ValidateGlobalDeclaration(Assignment* assign) {
}
DCHECK(target_info->type() != AsmType::None());
+ if (!global_variable) {
+ // Global variables have their types set in VariableTypeAnnotations.
+ SetTypeOf(value, target_info->type());
+ }
+ SetTypeOf(assign, target_info->type());
+ SetTypeOf(target, target_info->type());
return target_info->type();
}
@@ -830,6 +865,7 @@ AsmType* AsmTyper::ValidateFunctionTable(Assignment* assign) {
DCHECK(false);
FAIL(assign, "Redeclared global identifier in function table name.");
}
+ SetTypeOf(value, target_info->type());
return target_info->type();
}
@@ -854,7 +890,7 @@ AsmType* AsmTyper::ValidateFunctionTable(Assignment* assign) {
}
target_info->MarkDefined();
- DCHECK(target_info->type() == AsmType::None());
+ DCHECK(target_info->type() != AsmType::None());
SetTypeOf(value, target_info->type());
return target_info->type();
@@ -916,6 +952,8 @@ AsmType* AsmTyper::ValidateFunction(FunctionDeclaration* fun_decl) {
FAIL(proxy, "Redeclared parameter.");
}
parameter_types.push_back(type);
+ SetTypeOf(proxy, type);
+ SetTypeOf(expr, type);
}
if (annotated_parameters != fun->parameter_count()) {
@@ -952,6 +990,9 @@ AsmType* AsmTyper::ValidateFunction(FunctionDeclaration* fun_decl) {
if (!AddLocal(local->var(), local_info)) {
FAIL(initializer, "Redeclared local.");
}
+
+ SetTypeOf(local, type);
+ SetTypeOf(initializer, type);
}
// 5.2 Return Type Annotations
@@ -1018,6 +1059,8 @@ AsmType* AsmTyper::ValidateFunction(FunctionDeclaration* fun_decl) {
DCHECK(false);
FAIL(fun_decl, "Redeclared global identifier.");
}
+
+ SetTypeOf(fun, fun_type);
return fun_type;
}
@@ -1221,6 +1264,7 @@ AsmType* AsmTyper::ValidateSwitchStatement(SwitchStatement* stmt) {
CHECK(!has_default);
RECURSE(ValidateDefault(a_case));
has_default = true;
+ continue;
}
int32_t case_lbl;
@@ -1364,7 +1408,7 @@ bool IsUnaryMinus(BinaryOperation* binop) {
return false;
}
- return right_as_literal->raw_value()->ContainsDot() &&
+ return !right_as_literal->raw_value()->ContainsDot() &&
right_as_literal->raw_value()->AsNumber() == -1.0;
}
} // namespace
@@ -1391,6 +1435,7 @@ AsmType* AsmTyper::ValidateBinaryOperation(BinaryOperation* expr) {
}
AsmType* left_type;
RECURSE(left_type = ValidateExpression(expr->left()));
+ SetTypeOf(expr->right(), AsmType::Double());
UNOP_OVERLOAD(Signed, Double);
UNOP_OVERLOAD(Unsigned, Double);
UNOP_OVERLOAD(DoubleQ, Double);
@@ -1402,6 +1447,7 @@ AsmType* AsmTyper::ValidateBinaryOperation(BinaryOperation* expr) {
// *VIOLATION* the parser converts -x to x * -1.0.
AsmType* left_type;
RECURSE(left_type = ValidateExpression(expr->left()));
+ SetTypeOf(expr->right(), left_type);
UNOP_OVERLOAD(Int, Intish);
UNOP_OVERLOAD(DoubleQ, Double);
UNOP_OVERLOAD(FloatQ, Floatish);
@@ -1431,6 +1477,9 @@ AsmType* AsmTyper::ValidateBinaryOperation(BinaryOperation* expr) {
// This is the special ~~ operator.
AsmType* left_type;
RECURSE(left_type = ValidateExpression(left_as_binop->left()));
+ SetTypeOf(left_as_binop->right(), AsmType::FixNum());
+ SetTypeOf(left_as_binop, AsmType::Signed());
+ SetTypeOf(expr->right(), AsmType::FixNum());
UNOP_OVERLOAD(Double, Signed);
UNOP_OVERLOAD(FloatQ, Signed);
FAIL(left_as_binop, "Invalid type for conversion to signed.");
@@ -1456,24 +1505,21 @@ AsmType* AsmTyper::ValidateCommaExpression(BinaryOperation* comma) {
// (expr COMMA (expr COMMA (expr COMMA (... ))))
auto* left = comma->left();
- auto* left_as_binop = left->AsBinaryOperation();
- if (left_as_binop && left_as_binop->op() == Token::COMMA) {
- ValidateCommaExpression(left_as_binop);
- } else if (auto* left_as_call = left->AsCall()) {
- ValidateCall(AsmType::Void(), left_as_call);
+ if (auto* left_as_call = left->AsCall()) {
+ RECURSE(ValidateCall(AsmType::Void(), left_as_call));
} else {
- ValidateExpression(left);
+ RECURSE(ValidateExpression(left));
}
auto* right = comma->right();
- auto* right_as_binop = right->AsBinaryOperation();
- if (right_as_binop && right_as_binop->op() == Token::COMMA) {
- return ValidateCommaExpression(right_as_binop);
+ AsmType* right_type = nullptr;
+ if (auto* right_as_call = right->AsCall()) {
+ RECURSE(right_type = ValidateCall(AsmType::Void(), right_as_call));
} else {
- return ValidateExpression(right);
+ RECURSE(right_type = ValidateExpression(right));
}
- UNREACHABLE();
+ return right_type;
}
// 6.8.2 NumericLiteral
@@ -1500,7 +1546,6 @@ AsmType* AsmTyper::ValidateNumericLiteral(Literal* literal) {
return AsmType::Signed();
}
- static const uint32_t LargestFixNum = std::numeric_limits<int32_t>::max();
if (value <= LargestFixNum) {
return AsmType::FixNum();
}
@@ -1587,13 +1632,15 @@ AsmType* AsmTyper::ValidateAssignmentExpression(Assignment* assignment) {
ValidateHeapAccess(target_as_property, StoreToHeap));
// TODO(jpp): Change FloatishDoubleQ and FloatQDoubleQ so that they are base
- // classes for Floatish, DoubleQ, and FloatQ, and then invert this if so
- // that it reads more naturally as
- //
- // if (!value_type->IsA(allowed_store_types))
- if (allowed_store_types == AsmType::FloatishDoubleQ() ||
- allowed_store_types == AsmType::FloatQDoubleQ()) {
- if (!allowed_store_types->IsA(value_type)) {
+ // classes for Floatish, DoubleQ, and FloatQ.
+ if (allowed_store_types == AsmType::FloatishDoubleQ()) {
+ if (!value_type->IsA(AsmType::Floatish()) &&
+ !value_type->IsA(AsmType::DoubleQ())) {
+ FAIL(assignment, "Type mismatch in heap assignment.");
+ }
+ } else if (allowed_store_types == AsmType::FloatQDoubleQ()) {
+ if (!value_type->IsA(AsmType::FloatQ()) &&
+ !value_type->IsA(AsmType::DoubleQ())) {
FAIL(assignment, "Type mismatch in heap assignment.");
}
} else {
@@ -1778,6 +1825,7 @@ AsmType* AsmTyper::ValidateAdditiveExpression(BinaryOperation* binop,
left_as_binop->op() == Token::SUB)) {
RECURSE(left_type =
ValidateAdditiveExpression(left_as_binop, intish_count + 1));
+ SetTypeOf(left_as_binop, left_type);
} else {
RECURSE(left_type = ValidateExpression(left));
}
@@ -1790,6 +1838,7 @@ AsmType* AsmTyper::ValidateAdditiveExpression(BinaryOperation* binop,
right_as_binop->op() == Token::SUB)) {
RECURSE(right_type =
ValidateAdditiveExpression(right_as_binop, intish_count + 1));
+ SetTypeOf(right_as_binop, right_type);
} else {
RECURSE(right_type = ValidateExpression(right));
}
@@ -2084,32 +2133,14 @@ bool ExtractIndirectCallMask(Expression* expr, uint32_t* value) {
return base::bits::IsPowerOfTwo32(1 + *value);
}
-
-// TODO(jpp): Add a AsmType::ValidateCall is poorly designed. It can only handle
-// function declarations, not invocations. CheckInvocationOf temporarily works
-// around this limitation by converting each actual in actuals to a parameter
-// type before invoking prototype->ValidateCall. This is the wrong behavior for
-// FFIs (we need to pass Signed integers to FFIs, not Ints), so that case is
-// handled separately.
-bool CheckInvocationOf(AsmCallableType* prototype, AsmType* return_type,
- ZoneVector<AsmType*>* actuals) {
- if (auto* ffi = prototype->AsFFIType()) {
- return ffi->ValidateCall(return_type, *actuals) != AsmType::None();
- }
-
- for (size_t ii = 0; ii < actuals->size(); ++ii) {
- (*actuals)[ii] = (*actuals)[ii]->ToParameterType();
- }
- return prototype->ValidateCall(return_type, *actuals) != AsmType::None();
-}
-
} // namespace
AsmType* AsmTyper::ValidateCall(AsmType* return_type, Call* call) {
AsmType* float_coercion_type;
RECURSE(float_coercion_type = ValidateFloatCoercion(call));
if (float_coercion_type == AsmType::Float()) {
- return AsmType::Float();
+ SetTypeOf(call, AsmType::Float());
+ return return_type;
}
// TODO(jpp): we should be able to reuse the args vector's storage space.
@@ -2148,6 +2179,8 @@ AsmType* AsmTyper::ValidateCall(AsmType* return_type, Call* call) {
DCHECK(false);
FAIL(call, "Redeclared global identifier.");
}
+ SetTypeOf(call_var_proxy, reinterpret_cast<AsmType*>(call_type));
+ SetTypeOf(call, return_type);
return return_type;
}
@@ -2161,10 +2194,12 @@ AsmType* AsmTyper::ValidateCall(AsmType* return_type, Call* call) {
FAIL(call, "Foreign functions can't return float.");
}
- if (!CheckInvocationOf(callee_type, return_type, &args)) {
+ if (!callee_type->CanBeInvokedWith(return_type, args)) {
FAIL(call, "Function invocation does not match function type.");
}
+ SetTypeOf(call_var_proxy, call_var_info->type());
+ SetTypeOf(call, return_type);
return return_type;
}
@@ -2221,6 +2256,8 @@ AsmType* AsmTyper::ValidateCall(AsmType* return_type, Call* call) {
DCHECK(false);
FAIL(call, "Redeclared global identifier.");
}
+ SetTypeOf(call_property, reinterpret_cast<AsmType*>(call_type));
+ SetTypeOf(call, return_type);
return return_type;
}
@@ -2236,12 +2273,15 @@ AsmType* AsmTyper::ValidateCall(AsmType* return_type, Call* call) {
auto* previous_type_signature =
previous_type->signature()->AsFunctionType();
DCHECK(previous_type_signature != nullptr);
- if (!CheckInvocationOf(previous_type_signature, return_type, &args)) {
+ if (!previous_type_signature->CanBeInvokedWith(return_type, args)) {
+ // TODO(jpp): better error messages.
FAIL(call,
"Function pointer table signature does not match previous "
"signature.");
}
+ SetTypeOf(call_property, previous_type->signature());
+ SetTypeOf(call, return_type);
return return_type;
}
@@ -2280,6 +2320,7 @@ AsmType* AsmTyper::ValidateHeapAccess(Property* heap,
if (!obj_type->IsA(AsmType::Heap())) {
FAIL(heap, "Identifier does not represent a heap view.");
}
+ SetTypeOf(obj, obj_type);
if (auto* key_as_literal = heap->key()->AsLiteral()) {
if (key_as_literal->raw_value()->ContainsDot()) {
@@ -2371,6 +2412,7 @@ AsmType* AsmTyper::ValidateFloatCoercion(Call* call) {
RECURSE(arg_type = ValidateExpression(arg));
if (arg_type->IsA(AsmType::Floatish()) || arg_type->IsA(AsmType::DoubleQ()) ||
arg_type->IsA(AsmType::Signed()) || arg_type->IsA(AsmType::Unsigned())) {
+ SetTypeOf(call->expression(), fround_type_);
return AsmType::Float();
}
@@ -2395,9 +2437,11 @@ AsmType* AsmTyper::ParameterTypeAnnotations(Variable* parameter,
"Invalid parameter type annotation - should annotate a parameter.");
}
if (IsDoubleAnnotation(binop)) {
+ SetTypeOf(left, AsmType::Double());
return AsmType::Double();
}
if (IsIntAnnotation(binop)) {
+ SetTypeOf(left, AsmType::Int());
return AsmType::Int();
}
FAIL(binop, "Invalid parameter type annotation.");
@@ -2428,6 +2472,7 @@ AsmType* AsmTyper::ParameterTypeAnnotations(Variable* parameter,
"a parameter.");
}
+ SetTypeOf(src_expr, AsmType::Float());
return AsmType::Float();
}
@@ -2485,18 +2530,26 @@ AsmType* AsmTyper::ReturnTypeAnnotations(ReturnStatement* statement) {
AsmType* AsmTyper::VariableTypeAnnotations(Expression* initializer) {
if (auto* literal = initializer->AsLiteral()) {
if (literal->raw_value()->ContainsDot()) {
+ SetTypeOf(initializer, AsmType::Double());
return AsmType::Double();
}
int32_t i32;
uint32_t u32;
- if (literal->value()->ToInt32(&i32) || literal->value()->ToUint32(&u32)) {
- return AsmType::Int();
+ if (literal->value()->ToUint32(&u32)) {
+ if (u32 > LargestFixNum) {
+ SetTypeOf(initializer, AsmType::Unsigned());
+ } else {
+ SetTypeOf(initializer, AsmType::FixNum());
+ }
+ } else if (literal->value()->ToInt32(&i32)) {
+ SetTypeOf(initializer, AsmType::Signed());
+ } else {
+ FAIL(initializer, "Invalid type annotation - forbidden literal.");
}
- FAIL(initializer, "Invalid type annotation - forbidden literal.");
+ return AsmType::Int();
}
auto* call = initializer->AsCall();
- DCHECK(call != nullptr);
if (call == nullptr) {
FAIL(initializer,
"Invalid variable initialization - it should be a literal, or "
« no previous file with comments | « src/asmjs/asm-typer.h ('k') | src/asmjs/asm-types.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698