Commit 06f2a5c2 authored by Daniel Clifford's avatar Daniel Clifford Committed by Commit Bot

[torque] Implement parameter overloading in generics

This allows redifinitions of generics with the same name but differing parameter
type lists, e.g.

  macro coerce<Dest: type>(from: HeapObject): Dest;
  coerce<int32>(from: HeapObject): int32 {...}
  macro coerce<Dest: type>(from: Smi): Dest;
  coerce<int32>(from: Smi): int32 {...}

In order to allow multiple overloads of generic macros with the same name,
a more nuanced lookup of calls has been implemented using the
ParameterDifference utility class. There is still work to be done to unify
when ParameterDifference is used for lookup (e.g. removing it from operator
lookup when operators become simple aliases for macro names), but that work
will be done in a separate CL.

As part of this CL, the custom handling of "cast<>" operator in the .g4
grammar has been removed and replaced by a handful of equivalent overloads of
a generic "cast" macro.

Bug: v8:7793
Change-Id: Ibb2cdd3d58632b7f7f7ba683499f9688ae07f4f8
Reviewed-on: https://chromium-review.googlesource.com/1087873
Commit-Queue: Daniel Clifford <danno@chromium.org>
Reviewed-by: 's avatarTobias Tebbi <tebbi@chromium.org>
Cr-Commit-Position: refs/heads/master@{#53562}
parent 81666f7f
...@@ -235,32 +235,54 @@ extern operator '!' macro Word32BinaryNot(bool): bool; ...@@ -235,32 +235,54 @@ extern operator '!' macro Word32BinaryNot(bool): bool;
extern operator '.map' macro LoadMap(HeapObject): Map; extern operator '.map' macro LoadMap(HeapObject): Map;
extern operator '.map=' macro StoreMap(HeapObject, Map); extern operator '.map=' macro StoreMap(HeapObject, Map);
extern operator extern operator
'.instanceType' macro LoadInstanceType(HeapObject): InstanceType; '.instanceType' macro LoadInstanceType(HeapObject): InstanceType;
extern operator '.length' macro LoadStringLengthAsWord(String): intptr; extern operator '.length' macro LoadStringLengthAsWord(String): intptr;
extern operator '.length' macro GetArgumentsLength(constexpr Arguments): intptr; extern operator '.length' macro GetArgumentsLength(constexpr Arguments): intptr;
extern operator extern operator
'[]' macro GetArgumentValue(constexpr Arguments, intptr): Object; '[]' macro GetArgumentValue(constexpr Arguments, intptr): Object;
extern operator 'is<Smi>' macro TaggedIsSmi(Object): bool; extern operator 'is<Smi>' macro TaggedIsSmi(Object): bool;
extern operator 'isnt<Smi>' macro TaggedIsNotSmi(Object): bool; extern operator 'isnt<Smi>' macro TaggedIsNotSmi(Object): bool;
extern operator extern macro TaggedToJSDataView(Object): JSDataView labels CastError;
'cast<>' macro TaggedToJSDataView(Object): JSDataView labels CastError; extern macro TaggedToHeapObject(Object): HeapObject labels CastError;
extern operator extern macro TaggedToSmi(Object): Smi labels CastError;
'cast<>' macro TaggedToHeapObject(Object): HeapObject labels CastError; extern macro TaggedToJSArray(Object): JSArray labels CastError;
extern operator 'cast<>' macro TaggedToSmi(Object): Smi labels CastError; extern macro TaggedToCallable(Object): Callable labels CastError;
extern operator extern macro ConvertFixedArrayBaseToFixedArray(
'cast<>' macro TaggedToJSArray(Object): JSArray labels CastError;
extern operator
'cast<>' macro TaggedToCallable(Object): Callable labels CastError;
extern operator 'cast<>' macro ConvertFixedArrayBaseToFixedArray(
FixedArrayBase): FixedArray labels CastError; FixedArrayBase): FixedArray labels CastError;
extern operator 'cast<>' macro ConvertFixedArrayBaseToFixedDoubleArray( extern macro ConvertFixedArrayBaseToFixedDoubleArray(
FixedArrayBase): FixedDoubleArray labels CastError; FixedArrayBase): FixedDoubleArray labels CastError;
extern operator 'cast<>' macro TaggedToNumber( extern macro TaggedToNumber(Object): Number labels CastError;
Object): Number labels CastError;
macro cast<A : type>(o: Object): A labels CastError;
cast<Number>(o: Object): Number labels CastError {
return TaggedToNumber(o) otherwise CastError;
}
cast<HeapObject>(o: Object): HeapObject labels CastError {
return TaggedToHeapObject(o) otherwise CastError;
}
cast<Smi>(o: Object): Smi labels CastError {
return TaggedToSmi(o) otherwise CastError;
}
cast<JSDataView>(o: Object): JSDataView labels CastError {
return TaggedToJSDataView(o) otherwise CastError;
}
cast<Callable>(o: Object): Callable labels CastError {
return TaggedToCallable(o) otherwise CastError;
}
cast<JSArray>(o: Object): JSArray labels CastError {
return TaggedToJSArray(o) otherwise CastError;
}
macro cast<A : type>(o: FixedArrayBase): A labels CastError;
cast<FixedArray>(o: FixedArrayBase): FixedArray labels CastError {
return ConvertFixedArrayBaseToFixedArray(o) otherwise CastError;
}
cast<FixedDoubleArray>(o: FixedArrayBase): FixedDoubleArray labels CastError {
return ConvertFixedArrayBaseToFixedDoubleArray(o) otherwise CastError;
}
extern macro AllocateHeapNumberWithValue(float64): HeapNumber; extern macro AllocateHeapNumberWithValue(float64): HeapNumber;
...@@ -399,9 +421,10 @@ labels IfHole { ...@@ -399,9 +421,10 @@ labels IfHole {
} }
macro HasPropertyObject( macro HasPropertyObject(
o: Object, p: Object, c: Context, f: constexpr HasPropertyLookupMode): Oddball { o: Object, p: Object, c: Context,
f: constexpr HasPropertyLookupMode): Oddball {
try { try {
return HasProperty(cast<HeapObject>(o) otherwise CastError, p, c, f); return HasProperty((cast<HeapObject>(o) otherwise CastError), p, c, f);
} }
label CastError { label CastError {
return False; return False;
......
...@@ -5,16 +5,16 @@ ...@@ -5,16 +5,16 @@
#ifndef V8_BUILTINS_BUILTINS_DATA_VIEW_GEN_H_ #ifndef V8_BUILTINS_BUILTINS_DATA_VIEW_GEN_H_
#define V8_BUILTINS_BUILTINS_DATA_VIEW_GEN_H_ #define V8_BUILTINS_BUILTINS_DATA_VIEW_GEN_H_
#include "src/code-stub-assembler.h"
#include "src/elements-kind.h" #include "src/elements-kind.h"
#include "torque-generated/builtins-base-from-dsl-gen.h"
namespace v8 { namespace v8 {
namespace internal { namespace internal {
class DataViewBuiltinsAssembler : public CodeStubAssembler { class DataViewBuiltinsAssembler : public BaseBuiltinsFromDSLAssembler {
public: public:
explicit DataViewBuiltinsAssembler(compiler::CodeAssemblerState* state) explicit DataViewBuiltinsAssembler(compiler::CodeAssemblerState* state)
: CodeStubAssembler(state) {} : BaseBuiltinsFromDSLAssembler(state) {}
TNode<Smi> LoadDataViewByteOffset(TNode<JSDataView> data_view) { TNode<Smi> LoadDataViewByteOffset(TNode<JSDataView> data_view) {
return LoadObjectField<Smi>(data_view, JSDataView::kByteOffsetOffset); return LoadObjectField<Smi>(data_view, JSDataView::kByteOffsetOffset);
......
...@@ -5,15 +5,15 @@ ...@@ -5,15 +5,15 @@
#ifndef V8_BUILTINS_BUILTINS_TYPED_ARRAY_GEN_H_ #ifndef V8_BUILTINS_BUILTINS_TYPED_ARRAY_GEN_H_
#define V8_BUILTINS_BUILTINS_TYPED_ARRAY_GEN_H_ #define V8_BUILTINS_BUILTINS_TYPED_ARRAY_GEN_H_
#include "src/code-stub-assembler.h" #include "torque-generated/builtins-base-from-dsl-gen.h"
namespace v8 { namespace v8 {
namespace internal { namespace internal {
class TypedArrayBuiltinsAssembler : public CodeStubAssembler { class TypedArrayBuiltinsAssembler : public BaseBuiltinsFromDSLAssembler {
public: public:
explicit TypedArrayBuiltinsAssembler(compiler::CodeAssemblerState* state) explicit TypedArrayBuiltinsAssembler(compiler::CodeAssemblerState* state)
: CodeStubAssembler(state) {} : BaseBuiltinsFromDSLAssembler(state) {}
TNode<JSTypedArray> SpeciesCreateByLength(TNode<Context> context, TNode<JSTypedArray> SpeciesCreateByLength(TNode<Context> context,
TNode<JSTypedArray> exemplar, TNode<JSTypedArray> exemplar,
......
...@@ -17,7 +17,6 @@ JAVASCRIPT: 'javascript'; ...@@ -17,7 +17,6 @@ JAVASCRIPT: 'javascript';
IMPLICIT: 'implicit'; IMPLICIT: 'implicit';
DEFERRED: 'deferred'; DEFERRED: 'deferred';
IF: 'if'; IF: 'if';
CAST_KEYWORD: 'cast';
UNSAFE_CAST_KEYWORD: 'unsafe_cast'; UNSAFE_CAST_KEYWORD: 'unsafe_cast';
CONVERT_KEYWORD: 'convert'; CONVERT_KEYWORD: 'convert';
FOR: 'for'; FOR: 'for';
...@@ -216,7 +215,6 @@ primaryExpression ...@@ -216,7 +215,6 @@ primaryExpression
: helperCall : helperCall
| DECIMAL_LITERAL | DECIMAL_LITERAL
| STRING_LITERAL | STRING_LITERAL
| CAST_KEYWORD '<' type '>' '(' expression ')' OTHERWISE IDENTIFIER
| UNSAFE_CAST_KEYWORD '<' type '>' '(' expression ')' | UNSAFE_CAST_KEYWORD '<' type '>' '(' expression ')'
| CONVERT_KEYWORD '<' type '>' '(' expression ')' | CONVERT_KEYWORD '<' type '>' '(' expression ')'
| ('(' expression ')'); | ('(' expression ')');
......
This diff is collapsed.
...@@ -42,61 +42,60 @@ class TorqueLexer : public antlr4::Lexer { ...@@ -42,61 +42,60 @@ class TorqueLexer : public antlr4::Lexer {
IMPLICIT = 27, IMPLICIT = 27,
DEFERRED = 28, DEFERRED = 28,
IF = 29, IF = 29,
CAST_KEYWORD = 30, UNSAFE_CAST_KEYWORD = 30,
UNSAFE_CAST_KEYWORD = 31, CONVERT_KEYWORD = 31,
CONVERT_KEYWORD = 32, FOR = 32,
FOR = 33, WHILE = 33,
WHILE = 34, RETURN = 34,
RETURN = 35, CONSTEXPR = 35,
CONSTEXPR = 36, CONTINUE = 36,
CONTINUE = 37, BREAK = 37,
BREAK = 38, GOTO = 38,
GOTO = 39, OTHERWISE = 39,
OTHERWISE = 40, TRY = 40,
TRY = 41, LABEL = 41,
LABEL = 42, LABELS = 42,
LABELS = 43, TAIL = 43,
TAIL = 44, ISNT = 44,
ISNT = 45, IS = 45,
IS = 46, LET = 46,
LET = 47, EXTERN = 47,
EXTERN = 48, ASSERT_TOKEN = 48,
ASSERT_TOKEN = 49, CHECK_TOKEN = 49,
CHECK_TOKEN = 50, UNREACHABLE_TOKEN = 50,
UNREACHABLE_TOKEN = 51, DEBUG_TOKEN = 51,
DEBUG_TOKEN = 52, ASSIGNMENT = 52,
ASSIGNMENT = 53, ASSIGNMENT_OPERATOR = 53,
ASSIGNMENT_OPERATOR = 54, EQUAL = 54,
EQUAL = 55, PLUS = 55,
PLUS = 56, MINUS = 56,
MINUS = 57, MULTIPLY = 57,
MULTIPLY = 58, DIVIDE = 58,
DIVIDE = 59, MODULO = 59,
MODULO = 60, BIT_OR = 60,
BIT_OR = 61, BIT_AND = 61,
BIT_AND = 62, BIT_NOT = 62,
BIT_NOT = 63, MAX = 63,
MAX = 64, MIN = 64,
MIN = 65, NOT_EQUAL = 65,
NOT_EQUAL = 66, LESS_THAN = 66,
LESS_THAN = 67, LESS_THAN_EQUAL = 67,
LESS_THAN_EQUAL = 68, GREATER_THAN = 68,
GREATER_THAN = 69, GREATER_THAN_EQUAL = 69,
GREATER_THAN_EQUAL = 70, SHIFT_LEFT = 70,
SHIFT_LEFT = 71, SHIFT_RIGHT = 71,
SHIFT_RIGHT = 72, SHIFT_RIGHT_ARITHMETIC = 72,
SHIFT_RIGHT_ARITHMETIC = 73, VARARGS = 73,
VARARGS = 74, EQUALITY_OPERATOR = 74,
EQUALITY_OPERATOR = 75, INCREMENT = 75,
INCREMENT = 76, DECREMENT = 76,
DECREMENT = 77, NOT = 77,
NOT = 78, STRING_LITERAL = 78,
STRING_LITERAL = 79, IDENTIFIER = 79,
IDENTIFIER = 80, WS = 80,
WS = 81, BLOCK_COMMENT = 81,
BLOCK_COMMENT = 82, LINE_COMMENT = 82,
LINE_COMMENT = 83, DECIMAL_LITERAL = 83
DECIMAL_LITERAL = 84
}; };
explicit TorqueLexer(antlr4::CharStream* input); explicit TorqueLexer(antlr4::CharStream* input);
......
This source diff could not be displayed because it is too large. You can view the blob instead.
...@@ -42,61 +42,60 @@ class TorqueParser : public antlr4::Parser { ...@@ -42,61 +42,60 @@ class TorqueParser : public antlr4::Parser {
IMPLICIT = 27, IMPLICIT = 27,
DEFERRED = 28, DEFERRED = 28,
IF = 29, IF = 29,
CAST_KEYWORD = 30, UNSAFE_CAST_KEYWORD = 30,
UNSAFE_CAST_KEYWORD = 31, CONVERT_KEYWORD = 31,
CONVERT_KEYWORD = 32, FOR = 32,
FOR = 33, WHILE = 33,
WHILE = 34, RETURN = 34,
RETURN = 35, CONSTEXPR = 35,
CONSTEXPR = 36, CONTINUE = 36,
CONTINUE = 37, BREAK = 37,
BREAK = 38, GOTO = 38,
GOTO = 39, OTHERWISE = 39,
OTHERWISE = 40, TRY = 40,
TRY = 41, LABEL = 41,
LABEL = 42, LABELS = 42,
LABELS = 43, TAIL = 43,
TAIL = 44, ISNT = 44,
ISNT = 45, IS = 45,
IS = 46, LET = 46,
LET = 47, EXTERN = 47,
EXTERN = 48, ASSERT_TOKEN = 48,
ASSERT_TOKEN = 49, CHECK_TOKEN = 49,
CHECK_TOKEN = 50, UNREACHABLE_TOKEN = 50,
UNREACHABLE_TOKEN = 51, DEBUG_TOKEN = 51,
DEBUG_TOKEN = 52, ASSIGNMENT = 52,
ASSIGNMENT = 53, ASSIGNMENT_OPERATOR = 53,
ASSIGNMENT_OPERATOR = 54, EQUAL = 54,
EQUAL = 55, PLUS = 55,
PLUS = 56, MINUS = 56,
MINUS = 57, MULTIPLY = 57,
MULTIPLY = 58, DIVIDE = 58,
DIVIDE = 59, MODULO = 59,
MODULO = 60, BIT_OR = 60,
BIT_OR = 61, BIT_AND = 61,
BIT_AND = 62, BIT_NOT = 62,
BIT_NOT = 63, MAX = 63,
MAX = 64, MIN = 64,
MIN = 65, NOT_EQUAL = 65,
NOT_EQUAL = 66, LESS_THAN = 66,
LESS_THAN = 67, LESS_THAN_EQUAL = 67,
LESS_THAN_EQUAL = 68, GREATER_THAN = 68,
GREATER_THAN = 69, GREATER_THAN_EQUAL = 69,
GREATER_THAN_EQUAL = 70, SHIFT_LEFT = 70,
SHIFT_LEFT = 71, SHIFT_RIGHT = 71,
SHIFT_RIGHT = 72, SHIFT_RIGHT_ARITHMETIC = 72,
SHIFT_RIGHT_ARITHMETIC = 73, VARARGS = 73,
VARARGS = 74, EQUALITY_OPERATOR = 74,
EQUALITY_OPERATOR = 75, INCREMENT = 75,
INCREMENT = 76, DECREMENT = 76,
DECREMENT = 77, NOT = 77,
NOT = 78, STRING_LITERAL = 78,
STRING_LITERAL = 79, IDENTIFIER = 79,
IDENTIFIER = 80, WS = 80,
WS = 81, BLOCK_COMMENT = 81,
BLOCK_COMMENT = 82, LINE_COMMENT = 82,
LINE_COMMENT = 83, DECIMAL_LITERAL = 83
DECIMAL_LITERAL = 84
}; };
enum { enum {
...@@ -732,12 +731,9 @@ class TorqueParser : public antlr4::Parser { ...@@ -732,12 +731,9 @@ class TorqueParser : public antlr4::Parser {
HelperCallContext* helperCall(); HelperCallContext* helperCall();
antlr4::tree::TerminalNode* DECIMAL_LITERAL(); antlr4::tree::TerminalNode* DECIMAL_LITERAL();
antlr4::tree::TerminalNode* STRING_LITERAL(); antlr4::tree::TerminalNode* STRING_LITERAL();
antlr4::tree::TerminalNode* CAST_KEYWORD(); antlr4::tree::TerminalNode* UNSAFE_CAST_KEYWORD();
TypeContext* type(); TypeContext* type();
ExpressionContext* expression(); ExpressionContext* expression();
antlr4::tree::TerminalNode* OTHERWISE();
antlr4::tree::TerminalNode* IDENTIFIER();
antlr4::tree::TerminalNode* UNSAFE_CAST_KEYWORD();
antlr4::tree::TerminalNode* CONVERT_KEYWORD(); antlr4::tree::TerminalNode* CONVERT_KEYWORD();
void enterRule(antlr4::tree::ParseTreeListener* listener) override; void enterRule(antlr4::tree::ParseTreeListener* listener) override;
......
...@@ -546,11 +546,6 @@ antlrcpp::Any AstGenerator::visitPrimaryExpression( ...@@ -546,11 +546,6 @@ antlrcpp::Any AstGenerator::visitPrimaryExpression(
return implicit_cast<Expression*>(RegisterNode(new UnsafeCastExpression{ return implicit_cast<Expression*>(RegisterNode(new UnsafeCastExpression{
Pos(context), GetType(context->type()), Pos(context), GetType(context->type()),
context->expression()->accept(this).as<Expression*>()})); context->expression()->accept(this).as<Expression*>()}));
if (context->CAST_KEYWORD())
return implicit_cast<Expression*>(RegisterNode(new CastExpression{
Pos(context), GetType(context->type()),
context->IDENTIFIER()->getSymbol()->getText(),
context->expression()->accept(this).as<Expression*>()}));
return context->expression()->accept(this); return context->expression()->accept(this);
} }
......
...@@ -39,7 +39,6 @@ DECLARE_CONTEXTUAL_VARIABLE(CurrentSourcePosition, SourcePosition) ...@@ -39,7 +39,6 @@ DECLARE_CONTEXTUAL_VARIABLE(CurrentSourcePosition, SourcePosition)
V(ElementAccessExpression) \ V(ElementAccessExpression) \
V(AssignmentExpression) \ V(AssignmentExpression) \
V(IncrementDecrementExpression) \ V(IncrementDecrementExpression) \
V(CastExpression) \
V(UnsafeCastExpression) \ V(UnsafeCastExpression) \
V(ConvertExpression) V(ConvertExpression)
...@@ -302,16 +301,6 @@ struct NumberLiteralExpression : Expression { ...@@ -302,16 +301,6 @@ struct NumberLiteralExpression : Expression {
std::string number; std::string number;
}; };
struct CastExpression : Expression {
DEFINE_AST_NODE_LEAF_BOILERPLATE(CastExpression)
CastExpression(SourcePosition p, TypeExpression* t, std::string o,
Expression* v)
: Expression(kKind, p), type(t), otherwise(o), value(v) {}
TypeExpression* type;
std::string otherwise;
Expression* value;
};
struct ConvertExpression : Expression { struct ConvertExpression : Expression {
DEFINE_AST_NODE_LEAF_BOILERPLATE(ConvertExpression) DEFINE_AST_NODE_LEAF_BOILERPLATE(ConvertExpression)
ConvertExpression(SourcePosition p, TypeExpression* t, Expression* v) ConvertExpression(SourcePosition p, TypeExpression* t, Expression* v)
......
...@@ -34,6 +34,21 @@ std::ostream& operator<<(std::ostream& os, const RuntimeFunction& b) { ...@@ -34,6 +34,21 @@ std::ostream& operator<<(std::ostream& os, const RuntimeFunction& b) {
return os; return os;
} }
std::ostream& operator<<(std::ostream& os, const Generic& g) {
os << "generic " << g.name() << "<";
bool first = true;
for (auto t : g.declaration()->generic_parameters) {
if (!first) {
os << ", ";
}
first = false;
os << t << ": type";
}
os << ">";
return os;
}
} // namespace torque } // namespace torque
} // namespace internal } // namespace internal
} // namespace v8 } // namespace v8
...@@ -32,6 +32,7 @@ class Declarable { ...@@ -32,6 +32,7 @@ class Declarable {
kBuiltin, kBuiltin,
kRuntimeFunction, kRuntimeFunction,
kGeneric, kGeneric,
kGenericList,
kTypeAlias, kTypeAlias,
kLabel, kLabel,
kConstant kConstant
...@@ -46,6 +47,7 @@ class Declarable { ...@@ -46,6 +47,7 @@ class Declarable {
bool IsLabel() const { return kind() == kLabel; } bool IsLabel() const { return kind() == kLabel; }
bool IsVariable() const { return kind() == kVariable; } bool IsVariable() const { return kind() == kVariable; }
bool IsMacroList() const { return kind() == kMacroList; } bool IsMacroList() const { return kind() == kMacroList; }
bool IsGenericList() const { return kind() == kGenericList; }
bool IsConstant() const { return kind() == kConstant; } bool IsConstant() const { return kind() == kConstant; }
bool IsValue() const { return IsVariable() || IsConstant() || IsParameter(); } bool IsValue() const { return IsVariable() || IsConstant() || IsParameter(); }
virtual const char* type_name() const { return "<<unknown>>"; } virtual const char* type_name() const { return "<<unknown>>"; }
...@@ -286,6 +288,7 @@ class Generic : public Declarable { ...@@ -286,6 +288,7 @@ class Generic : public Declarable {
DECLARE_DECLARABLE_BOILERPLATE(Generic, generic); DECLARE_DECLARABLE_BOILERPLATE(Generic, generic);
GenericDeclaration* declaration() const { return declaration_; } GenericDeclaration* declaration() const { return declaration_; }
const std::string& name() const { return name_; }
Module* module() const { return module_; } Module* module() const { return module_; }
private: private:
...@@ -293,13 +296,31 @@ class Generic : public Declarable { ...@@ -293,13 +296,31 @@ class Generic : public Declarable {
Generic(const std::string& name, Module* module, Generic(const std::string& name, Module* module,
GenericDeclaration* declaration) GenericDeclaration* declaration)
: Declarable(Declarable::kGeneric), : Declarable(Declarable::kGeneric),
name_(name),
module_(module), module_(module),
declaration_(declaration) {} declaration_(declaration) {}
std::string name_;
Module* module_; Module* module_;
GenericDeclaration* declaration_; GenericDeclaration* declaration_;
}; };
class GenericList : public Declarable {
public:
DECLARE_DECLARABLE_BOILERPLATE(GenericList, generic_list);
const std::vector<Generic*>& list() { return list_; }
Generic* AddGeneric(Generic* generic) {
list_.push_back(generic);
return generic;
}
private:
friend class Declarations;
GenericList() : Declarable(Declarable::kGenericList) {}
std::vector<Generic*> list_;
};
typedef std::pair<Generic*, TypeVector> SpecializationKey; typedef std::pair<Generic*, TypeVector> SpecializationKey;
class TypeAlias : public Declarable { class TypeAlias : public Declarable {
...@@ -320,6 +341,7 @@ std::ostream& operator<<(std::ostream& os, const Callable& m); ...@@ -320,6 +341,7 @@ std::ostream& operator<<(std::ostream& os, const Callable& m);
std::ostream& operator<<(std::ostream& os, const Variable& v); std::ostream& operator<<(std::ostream& os, const Variable& v);
std::ostream& operator<<(std::ostream& os, const Builtin& b); std::ostream& operator<<(std::ostream& os, const Builtin& b);
std::ostream& operator<<(std::ostream& os, const RuntimeFunction& b); std::ostream& operator<<(std::ostream& os, const RuntimeFunction& b);
std::ostream& operator<<(std::ostream& os, const Generic& g);
#undef DECLARE_DECLARABLE_BOILERPLATE #undef DECLARE_DECLARABLE_BOILERPLATE
......
...@@ -193,8 +193,7 @@ void DeclarationVisitor::Visit(TorqueMacroDeclaration* decl, ...@@ -193,8 +193,7 @@ void DeclarationVisitor::Visit(TorqueMacroDeclaration* decl,
} }
void DeclarationVisitor::Visit(StandardDeclaration* decl) { void DeclarationVisitor::Visit(StandardDeclaration* decl) {
Signature signature = Signature signature = MakeSignature(decl->callable->signature.get());
MakeSignature(decl->callable, decl->callable->signature.get());
Visit(decl->callable, signature, decl->body); Visit(decl->callable, signature, decl->body);
} }
...@@ -203,33 +202,54 @@ void DeclarationVisitor::Visit(GenericDeclaration* decl) { ...@@ -203,33 +202,54 @@ void DeclarationVisitor::Visit(GenericDeclaration* decl) {
} }
void DeclarationVisitor::Visit(SpecializationDeclaration* decl) { void DeclarationVisitor::Visit(SpecializationDeclaration* decl) {
Generic* generic = declarations()->LookupGeneric(decl->name); GenericList* generic_list = declarations()->LookupGeneric(decl->name);
SpecializationKey key = {generic, GetTypeVector(decl->generic_parameters)};
CallableNode* callable = generic->declaration()->callable; // Find the matching generic specialization based on the concrete parameter
// list.
{ CallableNode* matching_callable = nullptr;
Signature signature_with_types = SpecializationKey matching_key;
MakeSignature(callable, decl->signature.get()); Signature signature_with_types = MakeSignature(decl->signature.get());
for (Generic* generic : generic_list->list()) {
SpecializationKey key = {generic, GetTypeVector(decl->generic_parameters)};
CallableNode* callable_candidate = generic->declaration()->callable;
// Abuse the Specialization nodes' scope to temporarily declare the // Abuse the Specialization nodes' scope to temporarily declare the
// specialization aliases for the generic types to compare signatures. This // specialization aliases for the generic types to compare signatures. This
// scope is never used for anything else, so it's OK to pollute it. // scope is never used for anything else, so it's OK to pollute it.
Declarations::NodeScopeActivator specialization_activator(declarations(), Declarations::CleanNodeScopeActivator specialization_activator(
decl); declarations(), decl);
DeclareSpecializedTypes(key); DeclareSpecializedTypes(key);
Signature generic_signature_with_types = Signature generic_signature_with_types =
MakeSignature(generic->declaration()->callable, MakeSignature(generic->declaration()->callable->signature.get());
generic->declaration()->callable->signature.get()); if (signature_with_types.HasSameTypesAs(generic_signature_with_types)) {
if (!signature_with_types.HasSameTypesAs(generic_signature_with_types)) { if (matching_callable != nullptr) {
std::stringstream stream; std::stringstream stream;
stream << "specialization of " << callable->name stream << "specialization of " << callable_candidate->name
<< " has incompatible parameter list or label list with generic " << " is ambigous, it matches more than one generic declaration ("
"definition"; << *matching_key.first << " and " << *key.first << ")";
ReportError(stream.str()); ReportError(stream.str());
}
matching_callable = callable_candidate;
matching_key = key;
} }
} }
SpecializeGeneric( if (matching_callable == nullptr) {
{key, callable, decl->signature.get(), decl->body, decl->pos}); std::stringstream stream;
stream << "specialization of " << decl->name
<< " doesn't match any generic declaration";
ReportError(stream.str());
}
// Make sure the declarations of the parameter types for the specialization
// are the ones from the matching generic.
{
Declarations::CleanNodeScopeActivator specialization_activator(
declarations(), decl);
DeclareSpecializedTypes(matching_key);
}
SpecializeGeneric({matching_key, matching_callable, decl->signature.get(),
decl->body, decl->pos});
} }
void DeclarationVisitor::Visit(ReturnStatement* stmt) { void DeclarationVisitor::Visit(ReturnStatement* stmt) {
...@@ -298,15 +318,22 @@ void DeclarationVisitor::Visit(TryLabelStatement* stmt) { ...@@ -298,15 +318,22 @@ void DeclarationVisitor::Visit(TryLabelStatement* stmt) {
void DeclarationVisitor::Visit(IdentifierExpression* expr) { void DeclarationVisitor::Visit(IdentifierExpression* expr) {
if (expr->generic_arguments.size() != 0) { if (expr->generic_arguments.size() != 0) {
Generic* generic = declarations()->LookupGeneric(expr->name);
TypeVector specialization_types; TypeVector specialization_types;
for (auto t : expr->generic_arguments) { for (auto t : expr->generic_arguments) {
specialization_types.push_back(declarations()->GetType(t)); specialization_types.push_back(declarations()->GetType(t));
} }
CallableNode* callable = generic->declaration()->callable; // Specialize all versions of the generic, since the exact parameter type
QueueGenericSpecialization({generic, specialization_types}, callable, // list cannot be resolved until the call's parameter expressions are
callable->signature.get(), // evaluated. This is an overly conservative but simple way to make sure
generic->declaration()->body); // that the correct specialization exists.
for (auto generic : declarations()->LookupGeneric(expr->name)->list()) {
CallableNode* callable = generic->declaration()->callable;
if (generic->declaration()->body) {
QueueGenericSpecialization({generic, specialization_types}, callable,
callable->signature.get(),
generic->declaration()->body);
}
}
} }
} }
...@@ -333,7 +360,7 @@ void DeclarationVisitor::Specialize(const SpecializationKey& key, ...@@ -333,7 +360,7 @@ void DeclarationVisitor::Specialize(const SpecializationKey& key,
// TODO(tebbi): The error should point to the source position where the // TODO(tebbi): The error should point to the source position where the
// instantiation was requested. // instantiation was requested.
CurrentSourcePosition::Scope scope(generic->declaration()->pos); CurrentSourcePosition::Scope pos_scope(generic->declaration()->pos);
size_t generic_parameter_count = size_t generic_parameter_count =
generic->declaration()->generic_parameters.size(); generic->declaration()->generic_parameters.size();
if (generic_parameter_count != key.second.size()) { if (generic_parameter_count != key.second.size()) {
...@@ -346,14 +373,16 @@ void DeclarationVisitor::Specialize(const SpecializationKey& key, ...@@ -346,14 +373,16 @@ void DeclarationVisitor::Specialize(const SpecializationKey& key,
ReportError(stream.str()); ReportError(stream.str());
} }
Signature type_signature;
{ {
// Manually activate the specialized generic's scope when declaring the // Manually activate the specialized generic's scope when declaring the
// generic parameter specializations. // generic parameter specializations.
Declarations::GenericScopeActivator scope(declarations(), key); Declarations::GenericScopeActivator namespace_scope(declarations(), key);
DeclareSpecializedTypes(key); DeclareSpecializedTypes(key);
type_signature = MakeSignature(signature);
} }
Visit(callable, MakeSignature(callable, signature), body); Visit(callable, type_signature, body);
} }
} // namespace torque } // namespace torque
......
...@@ -59,7 +59,6 @@ class DeclarationVisitor : public FileVisitor { ...@@ -59,7 +59,6 @@ class DeclarationVisitor : public FileVisitor {
Visit(expr->index); Visit(expr->index);
} }
void Visit(FieldAccessExpression* expr) { Visit(expr->object); } void Visit(FieldAccessExpression* expr) { Visit(expr->object); }
void Visit(CastExpression* expr) { Visit(expr->value); }
void Visit(UnsafeCastExpression* expr) { Visit(expr->value); } void Visit(UnsafeCastExpression* expr) { Visit(expr->value); }
void Visit(ConvertExpression* expr) { Visit(expr->value); } void Visit(ConvertExpression* expr) { Visit(expr->value); }
void Visit(BlockStatement* expr) { void Visit(BlockStatement* expr) {
......
...@@ -9,13 +9,15 @@ namespace v8 { ...@@ -9,13 +9,15 @@ namespace v8 {
namespace internal { namespace internal {
namespace torque { namespace torque {
Scope* Declarations::GetNodeScope(const AstNode* node) { Scope* Declarations::GetNodeScope(const AstNode* node, bool reset_scope) {
std::pair<const AstNode*, TypeVector> key( std::pair<const AstNode*, TypeVector> key(
node, current_generic_specialization_ == nullptr node, current_generic_specialization_ == nullptr
? TypeVector() ? TypeVector()
: current_generic_specialization_->second); : current_generic_specialization_->second);
auto i = scopes_.find(key); if (!reset_scope) {
if (i != scopes_.end()) return i->second; auto i = scopes_.find(key);
if (i != scopes_.end()) return i->second;
}
Scope* result = chain_.NewScope(); Scope* result = chain_.NewScope();
scopes_[key] = result; scopes_[key] = result;
return result; return result;
...@@ -175,11 +177,11 @@ Builtin* Declarations::LookupBuiltin(const std::string& name) { ...@@ -175,11 +177,11 @@ Builtin* Declarations::LookupBuiltin(const std::string& name) {
return nullptr; return nullptr;
} }
Generic* Declarations::LookupGeneric(const std::string& name) { GenericList* Declarations::LookupGeneric(const std::string& name) {
Declarable* declarable = Lookup(name); Declarable* declarable_list = Lookup(name);
if (declarable != nullptr) { if (declarable_list != nullptr) {
if (declarable->IsGeneric()) { if (declarable_list->IsGenericList()) {
return Generic::cast(declarable); return GenericList::cast(declarable_list);
} }
ReportError(name + " is not a generic"); ReportError(name + " is not a generic");
} }
...@@ -308,9 +310,20 @@ void Declarations::DeclareConstant(const std::string& name, const Type* type, ...@@ -308,9 +310,20 @@ void Declarations::DeclareConstant(const std::string& name, const Type* type,
Generic* Declarations::DeclareGeneric(const std::string& name, Module* module, Generic* Declarations::DeclareGeneric(const std::string& name, Module* module,
GenericDeclaration* generic) { GenericDeclaration* generic) {
CheckAlreadyDeclared(name, "generic"); auto previous = chain_.Lookup(name);
GenericList* generic_list = nullptr;
if (previous == nullptr) {
generic_list = new GenericList();
Declare(name, std::unique_ptr<Declarable>(generic_list));
} else if (!previous->IsGenericList()) {
std::stringstream s;
s << "cannot redeclare non-generic " << name << " as a generic";
ReportError(s.str());
} else {
generic_list = GenericList::cast(previous);
}
Generic* result = new Generic(name, module, generic); Generic* result = new Generic(name, module, generic);
Declare(name, std::unique_ptr<Generic>(result)); generic_list->AddGeneric(result);
generic_declaration_scopes_[result] = GetScopeChainSnapshot(); generic_declaration_scopes_[result] = GetScopeChainSnapshot();
return result; return result;
} }
......
...@@ -64,7 +64,7 @@ class Declarations { ...@@ -64,7 +64,7 @@ class Declarations {
Label* LookupLabel(const std::string& name); Label* LookupLabel(const std::string& name);
Generic* LookupGeneric(const std::string& name); GenericList* LookupGeneric(const std::string& name);
const AbstractType* DeclareAbstractType(const std::string& name, const AbstractType* DeclareAbstractType(const std::string& name,
const std::string& generated, const std::string& generated,
...@@ -109,12 +109,13 @@ class Declarations { ...@@ -109,12 +109,13 @@ class Declarations {
void PrintScopeChain() { chain_.Print(); } void PrintScopeChain() { chain_.Print(); }
class NodeScopeActivator; class NodeScopeActivator;
class CleanNodeScopeActivator;
class GenericScopeActivator; class GenericScopeActivator;
class ScopedGenericSpecializationKey; class ScopedGenericSpecializationKey;
class ScopedGenericScopeChainSnapshot; class ScopedGenericScopeChainSnapshot;
private: private:
Scope* GetNodeScope(const AstNode* node); Scope* GetNodeScope(const AstNode* node, bool reset_scope = false);
Scope* GetGenericScope(Generic* generic, const TypeVector& types); Scope* GetGenericScope(Generic* generic, const TypeVector& types);
template <class T> template <class T>
...@@ -153,6 +154,15 @@ class Declarations::NodeScopeActivator { ...@@ -153,6 +154,15 @@ class Declarations::NodeScopeActivator {
Scope::Activator activator_; Scope::Activator activator_;
}; };
class Declarations::CleanNodeScopeActivator {
public:
CleanNodeScopeActivator(Declarations* declarations, AstNode* node)
: activator_(declarations->GetNodeScope(node, true)) {}
private:
Scope::Activator activator_;
};
class Declarations::GenericScopeActivator { class Declarations::GenericScopeActivator {
public: public:
GenericScopeActivator(Declarations* declarations, GenericScopeActivator(Declarations* declarations,
......
...@@ -5,14 +5,13 @@ ...@@ -5,14 +5,13 @@
#include "src/torque/file-visitor.h" #include "src/torque/file-visitor.h"
#include "src/torque/declarable.h" #include "src/torque/declarable.h"
#include "src/torque/parameter-difference.h"
namespace v8 { namespace v8 {
namespace internal { namespace internal {
namespace torque { namespace torque {
Signature FileVisitor::MakeSignature(CallableNode* decl, Signature FileVisitor::MakeSignature(const CallableNodeSignature* signature) {
const CallableNodeSignature* signature) {
Declarations::NodeScopeActivator scope(declarations(), decl);
LabelDeclarationVector definition_vector; LabelDeclarationVector definition_vector;
for (auto label : signature->labels) { for (auto label : signature->labels) {
LabelDeclaration def = {label.name, GetTypeVector(label.types)}; LabelDeclaration def = {label.name, GetTypeVector(label.types)};
...@@ -45,25 +44,40 @@ Callable* FileVisitor::LookupCall(const std::string& name, ...@@ -45,25 +44,40 @@ Callable* FileVisitor::LookupCall(const std::string& name,
} else if (declarable->IsRuntimeFunction()) { } else if (declarable->IsRuntimeFunction()) {
result = RuntimeFunction::cast(declarable); result = RuntimeFunction::cast(declarable);
} else if (declarable->IsMacroList()) { } else if (declarable->IsMacroList()) {
for (auto& m : MacroList::cast(declarable)->list()) { std::vector<Macro*> candidates;
for (Macro* m : MacroList::cast(declarable)->list()) {
if (IsCompatibleSignature(m->signature().parameter_types, if (IsCompatibleSignature(m->signature().parameter_types,
parameter_types)) { parameter_types)) {
if (result != nullptr) { candidates.push_back(m);
std::stringstream stream;
stream << "multiple matching matching parameter list for macro "
<< name << ": (" << parameter_types << ") and ("
<< result->signature().parameter_types << ")";
ReportError(stream.str());
}
result = m;
} }
} }
if (result == nullptr) {
std::stringstream stream; auto is_better_candidate = [&](Macro* a, Macro* b) {
stream << "no matching matching parameter list for macro " << name return ParameterDifference(a->signature().parameter_types.types,
<< ": call parameters were (" << parameter_types << ")"; parameter_types)
ReportError(stream.str()); .StrictlyBetterThan(ParameterDifference(
b->signature().parameter_types.types, parameter_types));
};
if (!candidates.empty()) {
Macro* best = *std::min_element(candidates.begin(), candidates.end(),
is_better_candidate);
for (Macro* candidate : candidates) {
if (candidate != best && !is_better_candidate(best, candidate)) {
std::stringstream s;
s << "ambiguous macro \"" << name << "\" with types ("
<< parameter_types << "), candidates:";
for (Macro* m : candidates) {
s << "\n (" << m->signature().parameter_types << ") => "
<< m->signature().return_type;
}
ReportError(s.str());
}
}
return best;
} }
std::stringstream stream;
stream << "cannot find macro with name \"" << name << "\"";
ReportError(stream.str());
} else { } else {
std::stringstream stream; std::stringstream stream;
stream << "can't call " << declarable->type_name() << " " << name stream << "can't call " << declarable->type_name() << " " << name
...@@ -100,14 +114,13 @@ void FileVisitor::SpecializeGeneric( ...@@ -100,14 +114,13 @@ void FileVisitor::SpecializeGeneric(
completed_specializations_.end()) { completed_specializations_.end()) {
std::stringstream stream; std::stringstream stream;
stream << "cannot redeclare specialization of " stream << "cannot redeclare specialization of "
<< specialization.key.first->declaration()->callable->name << specialization.key.first->name() << " with types <"
<< " with types <" << specialization.key.second << ">"; << specialization.key.second << ">";
ReportError(stream.str()); ReportError(stream.str());
} }
if (!specialization.body) { if (!specialization.body) {
std::stringstream stream; std::stringstream stream;
stream << "missing specialization of " stream << "missing specialization of " << specialization.key.first->name()
<< specialization.key.first->declaration()->callable->name
<< " with types <" << specialization.key.second << ">"; << " with types <" << specialization.key.second << ">";
ReportError(stream.str()); ReportError(stream.str());
} }
......
...@@ -70,8 +70,7 @@ class FileVisitor { ...@@ -70,8 +70,7 @@ class FileVisitor {
Callable* LookupCall(const std::string& name, Callable* LookupCall(const std::string& name,
const TypeVector& parameter_types); const TypeVector& parameter_types);
Signature MakeSignature(CallableNode* decl, Signature MakeSignature(const CallableNodeSignature* signature);
const CallableNodeSignature* signature);
std::string GetGeneratedCallableName(const std::string& name, std::string GetGeneratedCallableName(const std::string& name,
const TypeVector& specialized_types); const TypeVector& specialized_types);
......
...@@ -3,6 +3,7 @@ ...@@ -3,6 +3,7 @@
// found in the LICENSE file. // found in the LICENSE file.
#include "src/torque/implementation-visitor.h" #include "src/torque/implementation-visitor.h"
#include "src/torque/parameter-difference.h"
#include "include/v8.h" #include "include/v8.h"
...@@ -151,7 +152,7 @@ void ImplementationVisitor::Visit(ModuleDeclaration* decl) { ...@@ -151,7 +152,7 @@ void ImplementationVisitor::Visit(ModuleDeclaration* decl) {
void ImplementationVisitor::Visit(TorqueMacroDeclaration* decl, void ImplementationVisitor::Visit(TorqueMacroDeclaration* decl,
const Signature& sig, Statement* body) { const Signature& sig, Statement* body) {
Signature signature = MakeSignature(decl, decl->signature.get()); Signature signature = MakeSignature(decl->signature.get());
std::string name = GetGeneratedCallableName( std::string name = GetGeneratedCallableName(
decl->name, declarations()->GetCurrentSpecializationTypeNamesVector()); decl->name, declarations()->GetCurrentSpecializationTypeNamesVector());
const TypeVector& list = signature.types(); const TypeVector& list = signature.types();
...@@ -501,13 +502,15 @@ VisitResult ImplementationVisitor::GetBuiltinCode(Builtin* builtin) { ...@@ -501,13 +502,15 @@ VisitResult ImplementationVisitor::GetBuiltinCode(Builtin* builtin) {
VisitResult ImplementationVisitor::Visit(IdentifierExpression* expr) { VisitResult ImplementationVisitor::Visit(IdentifierExpression* expr) {
std::string name = expr->name; std::string name = expr->name;
if (expr->generic_arguments.size() != 0) { if (expr->generic_arguments.size() != 0) {
Generic* generic = declarations()->LookupGeneric(expr->name); GenericList* generic_list = declarations()->LookupGeneric(expr->name);
TypeVector specialization_types = GetTypeVector(expr->generic_arguments); for (Generic* generic : generic_list->list()) {
name = GetGeneratedCallableName(name, specialization_types); TypeVector specialization_types = GetTypeVector(expr->generic_arguments);
CallableNode* callable = generic->declaration()->callable; name = GetGeneratedCallableName(name, specialization_types);
QueueGenericSpecialization({generic, specialization_types}, callable, CallableNode* callable = generic->declaration()->callable;
callable->signature.get(), QueueGenericSpecialization({generic, specialization_types}, callable,
generic->declaration()->body); callable->signature.get(),
generic->declaration()->body);
}
} }
if (Builtin* builtin = Builtin::DynamicCast(declarations()->Lookup(name))) { if (Builtin* builtin = Builtin::DynamicCast(declarations()->Lookup(name))) {
...@@ -517,13 +520,6 @@ VisitResult ImplementationVisitor::Visit(IdentifierExpression* expr) { ...@@ -517,13 +520,6 @@ VisitResult ImplementationVisitor::Visit(IdentifierExpression* expr) {
return GenerateFetchFromLocation(expr, GetLocationReference(expr)); return GenerateFetchFromLocation(expr, GetLocationReference(expr));
} }
VisitResult ImplementationVisitor::Visit(CastExpression* expr) {
Arguments args;
args.parameters = {Visit(expr->value)};
args.labels = LabelsFromIdentifiers({expr->otherwise});
return GenerateOperation("cast<>", args, declarations()->GetType(expr->type));
}
VisitResult ImplementationVisitor::Visit(UnsafeCastExpression* expr) { VisitResult ImplementationVisitor::Visit(UnsafeCastExpression* expr) {
const Type* type = declarations()->GetType(expr->type); const Type* type = declarations()->GetType(expr->type);
if (type->IsConstexpr()) { if (type->IsConstexpr()) {
...@@ -1083,62 +1079,6 @@ void ImplementationVisitor::GenerateMacroFunctionDeclaration( ...@@ -1083,62 +1079,6 @@ void ImplementationVisitor::GenerateMacroFunctionDeclaration(
o << ")"; o << ")";
} }
class ParameterDifference {
public:
ParameterDifference(const TypeVector& to, const TypeVector& from) {
DCHECK_EQ(to.size(), from.size());
for (size_t i = 0; i < to.size(); ++i) {
AddParameter(to[i], from[i]);
}
}
// An overload is selected if it is strictly better than all alternatives.
// This means that it has to be strictly better in at least one parameter,
// and better or equally good in all others.
//
// When comparing a pair of corresponding parameters of two overloads...
// ... they are considered equally good if:
// - They are equal.
// - Both require some implicit conversion.
// ... one is considered better if:
// - It is a strict subtype of the other.
// - It doesn't require an implicit conversion, while the other does.
bool StrictlyBetterThan(const ParameterDifference& other) const {
DCHECK_EQ(difference_.size(), other.difference_.size());
bool better_parameter_found = false;
for (size_t i = 0; i < difference_.size(); ++i) {
base::Optional<const Type*> a = difference_[i];
base::Optional<const Type*> b = other.difference_[i];
if (a == b) {
continue;
} else if (a && b && a != b && (*a)->IsSubtypeOf(*b)) {
DCHECK(!(*b)->IsSubtypeOf(*a));
better_parameter_found = true;
} else if (a && !b) {
better_parameter_found = true;
} else {
return false;
}
}
return better_parameter_found;
}
private:
// Pointwise difference between call arguments and a signature.
// {base::nullopt} means that an implicit conversion was necessary,
// otherwise we store the supertype found in the signature.
std::vector<base::Optional<const Type*>> difference_;
void AddParameter(const Type* to, const Type* from) {
if (from->IsSubtypeOf(to)) {
difference_.push_back(to);
} else if (IsAssignableFrom(to, from)) {
difference_.push_back(base::nullopt);
} else {
UNREACHABLE();
}
}
};
VisitResult ImplementationVisitor::GenerateOperation( VisitResult ImplementationVisitor::GenerateOperation(
const std::string& operation, Arguments arguments, const std::string& operation, Arguments arguments,
...@@ -1563,14 +1503,30 @@ void ImplementationVisitor::Visit(StandardDeclaration* decl) { ...@@ -1563,14 +1503,30 @@ void ImplementationVisitor::Visit(StandardDeclaration* decl) {
} }
void ImplementationVisitor::Visit(SpecializationDeclaration* decl) { void ImplementationVisitor::Visit(SpecializationDeclaration* decl) {
Generic* generic = declarations()->LookupGeneric(decl->name); Signature signature_with_types = MakeSignature(decl->signature.get());
TypeVector specialization_types = GetTypeVector(decl->generic_parameters); Declarations::NodeScopeActivator specialization_activator(declarations(),
CallableNode* callable = generic->declaration()->callable; decl);
SpecializeGeneric({{generic, specialization_types}, GenericList* generic_list = declarations()->LookupGeneric(decl->name);
callable, for (Generic* generic : generic_list->list()) {
decl->signature.get(), CallableNode* callable = generic->declaration()->callable;
decl->body, Signature generic_signature_with_types =
decl->pos}); MakeSignature(callable->signature.get());
if (signature_with_types.HasSameTypesAs(generic_signature_with_types)) {
TypeVector specialization_types = GetTypeVector(decl->generic_parameters);
SpecializeGeneric({{generic, specialization_types},
callable,
decl->signature.get(),
decl->body,
decl->pos});
return;
}
}
// Because the DeclarationVisitor already performed the same lookup
// as above to find aspecialization match and already threw if it didn't
// find one, failure to find a match here should never happen.
// TODO(danno): Remember the specialization found in the declaration visitor
// so that the lookup doesn't have to be repeated here.
UNREACHABLE();
} }
VisitResult ImplementationVisitor::Visit(CallExpression* expr, VisitResult ImplementationVisitor::Visit(CallExpression* expr,
...@@ -1579,14 +1535,18 @@ VisitResult ImplementationVisitor::Visit(CallExpression* expr, ...@@ -1579,14 +1535,18 @@ VisitResult ImplementationVisitor::Visit(CallExpression* expr,
std::string name = expr->callee.name; std::string name = expr->callee.name;
bool has_template_arguments = expr->callee.generic_arguments.size() != 0; bool has_template_arguments = expr->callee.generic_arguments.size() != 0;
if (has_template_arguments) { if (has_template_arguments) {
Generic* generic = declarations()->LookupGeneric(expr->callee.name);
TypeVector specialization_types = TypeVector specialization_types =
GetTypeVector(expr->callee.generic_arguments); GetTypeVector(expr->callee.generic_arguments);
name = GetGeneratedCallableName(name, specialization_types); name = GetGeneratedCallableName(name, specialization_types);
CallableNode* callable = generic->declaration()->callable; for (auto generic :
QueueGenericSpecialization({generic, specialization_types}, callable, declarations()->LookupGeneric(expr->callee.name)->list()) {
callable->signature.get(), CallableNode* callable = generic->declaration()->callable;
generic->declaration()->body); if (generic->declaration()->body) {
QueueGenericSpecialization({generic, specialization_types}, callable,
callable->signature.get(),
generic->declaration()->body);
}
}
} }
for (Expression* arg : expr->arguments) for (Expression* arg : expr->arguments)
arguments.parameters.push_back(Visit(arg)); arguments.parameters.push_back(Visit(arg));
......
...@@ -83,7 +83,6 @@ class ImplementationVisitor : public FileVisitor { ...@@ -83,7 +83,6 @@ class ImplementationVisitor : public FileVisitor {
return GenerateFetchFromLocation(expr, GetLocationReference(expr)); return GenerateFetchFromLocation(expr, GetLocationReference(expr));
} }
VisitResult Visit(CastExpression* expr);
VisitResult Visit(UnsafeCastExpression* expr); VisitResult Visit(UnsafeCastExpression* expr);
VisitResult Visit(ConvertExpression* expr); VisitResult Visit(ConvertExpression* expr);
...@@ -227,7 +226,7 @@ class ImplementationVisitor : public FileVisitor { ...@@ -227,7 +226,7 @@ class ImplementationVisitor : public FileVisitor {
const CallableNodeSignature* signature, const CallableNodeSignature* signature,
Statement* body) override { Statement* body) override {
Declarations::GenericScopeActivator scope(declarations(), key); Declarations::GenericScopeActivator scope(declarations(), key);
Visit(callable, MakeSignature(callable, signature), body); Visit(callable, MakeSignature(signature), body);
} }
std::string NewTempVariable(); std::string NewTempVariable();
......
// Copyright 2018 the V8 project authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#ifndef V8_TORQUE_PARAMETER_DIFFERENCE_H_
#define V8_TORQUE_PARAMETER_DIFFERENCE_H_
#include <vector>
#include "src/torque/types.h"
namespace v8 {
namespace internal {
namespace torque {
class ParameterDifference {
public:
ParameterDifference(const TypeVector& to, const TypeVector& from) {
DCHECK_EQ(to.size(), from.size());
for (size_t i = 0; i < to.size(); ++i) {
AddParameter(to[i], from[i]);
}
}
// An overload is selected if it is strictly better than all alternatives.
// This means that it has to be strictly better in at least one parameter,
// and better or equally good in all others.
//
// When comparing a pair of corresponding parameters of two overloads...
// ... they are considered equally good if:
// - They are equal.
// - Both require some implicit conversion.
// ... one is considered better if:
// - It is a strict subtype of the other.
// - It doesn't require an implicit conversion, while the other does.
bool StrictlyBetterThan(const ParameterDifference& other) const {
DCHECK_EQ(difference_.size(), other.difference_.size());
bool better_parameter_found = false;
for (size_t i = 0; i < difference_.size(); ++i) {
base::Optional<const Type*> a = difference_[i];
base::Optional<const Type*> b = other.difference_[i];
if (a == b) {
continue;
} else if (a && b && a != b && (*a)->IsSubtypeOf(*b)) {
DCHECK(!(*b)->IsSubtypeOf(*a));
better_parameter_found = true;
} else if (a && !b) {
better_parameter_found = true;
} else {
return false;
}
}
return better_parameter_found;
}
private:
// Pointwise difference between call arguments and a signature.
// {base::nullopt} means that an implicit conversion was necessary,
// otherwise we store the supertype found in the signature.
std::vector<base::Optional<const Type*>> difference_;
void AddParameter(const Type* to, const Type* from) {
if (from->IsSubtypeOf(to)) {
difference_.push_back(to);
} else if (IsAssignableFrom(to, from)) {
difference_.push_back(base::nullopt);
} else {
UNREACHABLE();
}
}
};
} // namespace torque
} // namespace internal
} // namespace v8
#endif // V8_TORQUE_PARAMETER_DIFFERENCE_H_
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