Commit 3d2cb0b4 authored by Daniel Clifford's avatar Daniel Clifford Committed by Commit Bot

[torque]: Implement Generics for Builtins and Macros

Including specialization, e.g.:

  // Declare parameterized generic
  macro GenericMacroTest<T: type>(param: T): Object {
    return Undefined;
  }

  // Declare specialization of generic
  GenericMacroTest<Object>(param: Object): Object {
    return param;
  }

  ...
  assert(GenericMacroTest<Smi>(0) == Undefined);
  assert(GenericMacroTest<Smi>(1) == Undefined);
  assert(GenericMacroTest<Object>(Null) == Null);
  assert(GenericMacroTest<Object>(False) == False);
  ...

Known issue: specialization doesn't rigorously checked to verify
that specialization signature precisely matches generic declaration.

Change-Id: I9d9d96da4c5c8c9a76550844680e9e133a5edaed
Reviewed-on: https://chromium-review.googlesource.com/1043986
Commit-Queue: Daniel Clifford <danno@chromium.org>
Reviewed-by: 's avatarTobias Tebbi <tebbi@chromium.org>
Cr-Commit-Position: refs/heads/master@{#53203}
parent c1928181
......@@ -35,6 +35,7 @@ TAIL: 'tail';
ISNT: 'isnt';
IS: 'is';
LET: 'let';
EXTERN: 'extern';
ASSERT: 'assert';
UNREACHABLE_TOKEN: 'unreachable';
DEBUG_TOKEN: 'debug';
......@@ -118,6 +119,9 @@ DECIMAL_LITERAL
type : CONSTEXPR? IDENTIFIER;
typeList : '(' type? (',' type)* ')';
optionalGenericSpecializationTypeList: ('<' IDENTIFIER (',' IDENTIFIER)* '>')?;
optionalGenericTypeList: ('<' IDENTIFIER ':' 'type' (',' IDENTIFIER ':' 'type')* '>')?;
typeListMaybeVarArgs: '(' type? (',' type)* (',' VARARGS)? ')'
| '(' VARARGS ')';
......@@ -219,7 +223,7 @@ forOfLoop: FOR '(' variableDeclaration 'of' expression forOfRange ')' statementB
argument: expression;
argumentList: '(' argument? (',' argument)* ')';
helperCall: (MIN | MAX | IDENTIFIER) argumentList optionalOtherwise;
helperCall: (MIN | MAX | IDENTIFIER) optionalGenericSpecializationTypeList argumentList optionalOtherwise;
labelReference: IDENTIFIER;
variableDeclaration: LET IDENTIFIER ':' type;
......@@ -265,16 +269,18 @@ generatesDeclaration: 'generates' STRING_LITERAL;
constexprDeclaration: 'constexpr' STRING_LITERAL;
typeDeclaration : 'type' IDENTIFIER extendsDeclaration? generatesDeclaration? constexprDeclaration?';';
externalBuiltin : 'extern' JAVASCRIPT? BUILTIN IDENTIFIER typeList optionalType ';';
externalMacro : 'extern' (IMPLICIT? 'operator' STRING_LITERAL)? MACRO IDENTIFIER typeListMaybeVarArgs optionalType optionalLabelList ';';
externalRuntime : 'extern' RUNTIME IDENTIFIER typeListMaybeVarArgs optionalType ';';
builtinDeclaration : JAVASCRIPT? BUILTIN IDENTIFIER parameterList optionalType helperBody;
macroDeclaration : MACRO IDENTIFIER parameterList optionalType optionalLabelList helperBody;
externalBuiltin : EXTERN JAVASCRIPT? BUILTIN IDENTIFIER optionalGenericTypeList typeList optionalType ';';
externalMacro : EXTERN (IMPLICIT? 'operator' STRING_LITERAL)? MACRO IDENTIFIER optionalGenericTypeList typeListMaybeVarArgs optionalType optionalLabelList ';';
externalRuntime : EXTERN RUNTIME IDENTIFIER typeListMaybeVarArgs optionalType ';';
builtinDeclaration : JAVASCRIPT? BUILTIN IDENTIFIER optionalGenericTypeList parameterList optionalType helperBody;
genericSpecialization: IDENTIFIER optionalGenericSpecializationTypeList parameterList optionalType optionalLabelList helperBody;
macroDeclaration : MACRO IDENTIFIER optionalGenericTypeList parameterList optionalType optionalLabelList helperBody;
constDeclaration : 'const' IDENTIFIER ':' type '=' STRING_LITERAL ';';
declaration
: typeDeclaration
| builtinDeclaration
| genericSpecialization
| macroDeclaration
| externalMacro
| externalBuiltin
......
......@@ -24,6 +24,18 @@ class TorqueBaseListener : public TorqueListener {
void enterTypeList(TorqueParser::TypeListContext* /*ctx*/) override {}
void exitTypeList(TorqueParser::TypeListContext* /*ctx*/) override {}
void enterOptionalGenericSpecializationTypeList(
TorqueParser::OptionalGenericSpecializationTypeListContext* /*ctx*/)
override {}
void exitOptionalGenericSpecializationTypeList(
TorqueParser::OptionalGenericSpecializationTypeListContext* /*ctx*/)
override {}
void enterOptionalGenericTypeList(
TorqueParser::OptionalGenericTypeListContext* /*ctx*/) override {}
void exitOptionalGenericTypeList(
TorqueParser::OptionalGenericTypeListContext* /*ctx*/) override {}
void enterTypeListMaybeVarArgs(
TorqueParser::TypeListMaybeVarArgsContext* /*ctx*/) override {}
void exitTypeListMaybeVarArgs(
......@@ -291,6 +303,11 @@ class TorqueBaseListener : public TorqueListener {
void exitBuiltinDeclaration(
TorqueParser::BuiltinDeclarationContext* /*ctx*/) override {}
void enterGenericSpecialization(
TorqueParser::GenericSpecializationContext* /*ctx*/) override {}
void exitGenericSpecialization(
TorqueParser::GenericSpecializationContext* /*ctx*/) override {}
void enterMacroDeclaration(
TorqueParser::MacroDeclarationContext* /*ctx*/) override {}
void exitMacroDeclaration(
......
......@@ -26,6 +26,17 @@ class TorqueBaseVisitor : public TorqueVisitor {
return visitChildren(ctx);
}
antlrcpp::Any visitOptionalGenericSpecializationTypeList(
TorqueParser::OptionalGenericSpecializationTypeListContext* ctx)
override {
return visitChildren(ctx);
}
antlrcpp::Any visitOptionalGenericTypeList(
TorqueParser::OptionalGenericTypeListContext* ctx) override {
return visitChildren(ctx);
}
antlrcpp::Any visitTypeListMaybeVarArgs(
TorqueParser::TypeListMaybeVarArgsContext* ctx) override {
return visitChildren(ctx);
......@@ -310,6 +321,11 @@ class TorqueBaseVisitor : public TorqueVisitor {
return visitChildren(ctx);
}
antlrcpp::Any visitGenericSpecialization(
TorqueParser::GenericSpecializationContext* ctx) override {
return visitChildren(ctx);
}
antlrcpp::Any visitMacroDeclaration(
TorqueParser::MacroDeclarationContext* ctx) override {
return visitChildren(ctx);
......
This diff is collapsed.
......@@ -33,33 +33,33 @@ class TorqueLexer : public antlr4::Lexer {
T__17 = 18,
T__18 = 19,
T__19 = 20,
T__20 = 21,
MACRO = 22,
BUILTIN = 23,
RUNTIME = 24,
MODULE = 25,
JAVASCRIPT = 26,
IMPLICIT = 27,
DEFERRED = 28,
IF = 29,
CAST_KEYWORD = 30,
CONVERT_KEYWORD = 31,
FOR = 32,
WHILE = 33,
RETURN = 34,
CONSTEXPR = 35,
CONTINUE = 36,
BREAK = 37,
GOTO = 38,
OTHERWISE = 39,
TRY = 40,
CATCH = 41,
LABEL = 42,
LABELS = 43,
TAIL = 44,
ISNT = 45,
IS = 46,
LET = 47,
MACRO = 21,
BUILTIN = 22,
RUNTIME = 23,
MODULE = 24,
JAVASCRIPT = 25,
IMPLICIT = 26,
DEFERRED = 27,
IF = 28,
CAST_KEYWORD = 29,
CONVERT_KEYWORD = 30,
FOR = 31,
WHILE = 32,
RETURN = 33,
CONSTEXPR = 34,
CONTINUE = 35,
BREAK = 36,
GOTO = 37,
OTHERWISE = 38,
TRY = 39,
CATCH = 40,
LABEL = 41,
LABELS = 42,
TAIL = 43,
ISNT = 44,
IS = 45,
LET = 46,
EXTERN = 47,
ASSERT = 48,
UNREACHABLE_TOKEN = 49,
DEBUG_TOKEN = 50,
......
......@@ -23,6 +23,16 @@ class TorqueListener : public antlr4::tree::ParseTreeListener {
virtual void enterTypeList(TorqueParser::TypeListContext* ctx) = 0;
virtual void exitTypeList(TorqueParser::TypeListContext* ctx) = 0;
virtual void enterOptionalGenericSpecializationTypeList(
TorqueParser::OptionalGenericSpecializationTypeListContext* ctx) = 0;
virtual void exitOptionalGenericSpecializationTypeList(
TorqueParser::OptionalGenericSpecializationTypeListContext* ctx) = 0;
virtual void enterOptionalGenericTypeList(
TorqueParser::OptionalGenericTypeListContext* ctx) = 0;
virtual void exitOptionalGenericTypeList(
TorqueParser::OptionalGenericTypeListContext* ctx) = 0;
virtual void enterTypeListMaybeVarArgs(
TorqueParser::TypeListMaybeVarArgsContext* ctx) = 0;
virtual void exitTypeListMaybeVarArgs(
......@@ -274,6 +284,11 @@ class TorqueListener : public antlr4::tree::ParseTreeListener {
virtual void exitBuiltinDeclaration(
TorqueParser::BuiltinDeclarationContext* ctx) = 0;
virtual void enterGenericSpecialization(
TorqueParser::GenericSpecializationContext* ctx) = 0;
virtual void exitGenericSpecialization(
TorqueParser::GenericSpecializationContext* ctx) = 0;
virtual void enterMacroDeclaration(
TorqueParser::MacroDeclarationContext* ctx) = 0;
virtual void exitMacroDeclaration(
......
This diff is collapsed.
This diff is collapsed.
......@@ -25,6 +25,12 @@ class TorqueVisitor : public antlr4::tree::AbstractParseTreeVisitor {
virtual antlrcpp::Any visitTypeList(
TorqueParser::TypeListContext* context) = 0;
virtual antlrcpp::Any visitOptionalGenericSpecializationTypeList(
TorqueParser::OptionalGenericSpecializationTypeListContext* context) = 0;
virtual antlrcpp::Any visitOptionalGenericTypeList(
TorqueParser::OptionalGenericTypeListContext* context) = 0;
virtual antlrcpp::Any visitTypeListMaybeVarArgs(
TorqueParser::TypeListMaybeVarArgsContext* context) = 0;
......@@ -201,6 +207,9 @@ class TorqueVisitor : public antlr4::tree::AbstractParseTreeVisitor {
virtual antlrcpp::Any visitBuiltinDeclaration(
TorqueParser::BuiltinDeclarationContext* context) = 0;
virtual antlrcpp::Any visitGenericSpecialization(
TorqueParser::GenericSpecializationContext* context) = 0;
virtual antlrcpp::Any visitMacroDeclaration(
TorqueParser::MacroDeclarationContext* context) = 0;
......
This diff is collapsed.
......@@ -41,6 +41,9 @@ class AstGenerator : public TorqueBaseVisitor {
antlrcpp::Any visitExternalRuntime(
TorqueParser::ExternalRuntimeContext* context) override;
antlrcpp::Any visitGenericSpecialization(
TorqueParser::GenericSpecializationContext* context) override;
antlrcpp::Any visitConstDeclaration(
TorqueParser::ConstDeclarationContext* context) override;
......
......@@ -58,19 +58,25 @@ struct SourcePosition {
#define AST_DECLARATION_NODE_KIND_LIST(V) \
V(TypeDeclaration) \
V(MacroDeclaration) \
V(ExternalMacroDeclaration) \
V(BuiltinDeclaration) \
V(ExternalBuiltinDeclaration) \
V(ExternalRuntimeDeclaration) \
V(StandardDeclaration) \
V(GenericDeclaration) \
V(SpecializationDeclaration) \
V(ConstDeclaration) \
V(DefaultModuleDeclaration) \
V(ExplicitModuleDeclaration)
#define AST_CALLABLE_NODE_KIND_LIST(V) \
V(TorqueMacroDeclaration) \
V(TorqueBuiltinDeclaration) \
V(ExternalMacroDeclaration) \
V(ExternalBuiltinDeclaration) \
V(ExternalRuntimeDeclaration)
#define AST_NODE_KIND_LIST(V) \
AST_EXPRESSION_NODE_KIND_LIST(V) \
AST_STATEMENT_NODE_KIND_LIST(V) \
AST_DECLARATION_NODE_KIND_LIST(V) \
AST_CALLABLE_NODE_KIND_LIST(V) \
V(CatchBlock) \
V(LabelBlock)
......@@ -211,14 +217,17 @@ class Ast {
struct CallExpression : Expression {
DEFINE_AST_NODE_LEAF_BOILERPLATE(CallExpression)
CallExpression(SourcePosition p, std::string c, bool o,
std::vector<Expression*> a, std::vector<std::string> l)
std::vector<std::string> ga, std::vector<Expression*> a,
std::vector<std::string> l)
: Expression(kKind, p),
callee(std::move(c)),
is_operator(o),
generic_arguments(ga),
arguments(std::move(a)),
labels(l) {}
std::string callee;
bool is_operator;
std::vector<std::string> generic_arguments;
std::vector<Expression*> arguments;
std::vector<std::string> labels;
};
......@@ -516,86 +525,112 @@ struct LabelAndTypes {
typedef std::vector<LabelAndTypes> LabelAndTypesVector;
struct MacroDeclaration : Declaration {
DEFINE_AST_NODE_LEAF_BOILERPLATE(MacroDeclaration)
MacroDeclaration(SourcePosition p, std::string n, ParameterList pl,
std::string r, const LabelAndTypesVector& l, Statement* b)
: Declaration(kKind, p),
name(std::move(n)),
parameters(std::move(pl)),
return_type(std::move(r)),
labels(std::move(l)),
body(std::move(b)) {}
std::string name;
struct CallableNodeSignature {
ParameterList parameters;
std::string return_type;
LabelAndTypesVector labels;
Statement* body;
};
struct ExternalMacroDeclaration : Declaration {
DEFINE_AST_NODE_LEAF_BOILERPLATE(ExternalMacroDeclaration)
ExternalMacroDeclaration(SourcePosition p, std::string n, bool i,
base::Optional<std::string> o, ParameterList pl,
std::string r, const LabelAndTypesVector& l)
: Declaration(kKind, p),
struct CallableNode : AstNode {
CallableNode(AstNode::Kind kind, SourcePosition p, std::string n,
ParameterList pl, std::string r, const LabelAndTypesVector& l)
: AstNode(kind, p),
name(std::move(n)),
implicit(i),
op(std::move(o)),
parameters(std::move(pl)),
return_type(std::move(r)),
labels(std::move(l)) {}
signature(new CallableNodeSignature{pl, r, l}) {}
DEFINE_AST_NODE_INNER_BOILERPLATE(CallableNode)
std::string name;
std::unique_ptr<CallableNodeSignature> signature;
};
struct MacroDeclaration : CallableNode {
DEFINE_AST_NODE_INNER_BOILERPLATE(MacroDeclaration)
MacroDeclaration(AstNode::Kind kind, SourcePosition p, std::string n, bool i,
base::Optional<std::string> o, ParameterList pl,
std::string r, const LabelAndTypesVector& l)
: CallableNode(kind, p, n, pl, r, l), implicit(i), op(std::move(o)) {}
bool implicit;
base::Optional<std::string> op;
ParameterList parameters;
std::string return_type;
LabelAndTypesVector labels;
};
struct BuiltinDeclaration : Declaration {
DEFINE_AST_NODE_LEAF_BOILERPLATE(BuiltinDeclaration)
BuiltinDeclaration(SourcePosition p, bool j, std::string n, ParameterList pl,
std::string r, Statement* b)
: Declaration(kKind, p),
javascript_linkage(j),
name(std::move(n)),
parameters(std::move(pl)),
return_type(std::move(r)),
body(std::move(b)) {}
struct ExternalMacroDeclaration : MacroDeclaration {
DEFINE_AST_NODE_LEAF_BOILERPLATE(ExternalMacroDeclaration)
ExternalMacroDeclaration(SourcePosition p, std::string n, bool i,
base::Optional<std::string> o, ParameterList pl,
std::string r, const LabelAndTypesVector& l)
: MacroDeclaration(kKind, p, n, i, o, pl, r, l) {}
};
struct TorqueMacroDeclaration : MacroDeclaration {
DEFINE_AST_NODE_LEAF_BOILERPLATE(TorqueMacroDeclaration)
TorqueMacroDeclaration(SourcePosition p, std::string n, ParameterList pl,
std::string r, const LabelAndTypesVector& l)
: MacroDeclaration(kKind, p, n, false, {}, pl, r, l) {}
};
struct BuiltinDeclaration : CallableNode {
BuiltinDeclaration(AstNode::Kind kind, SourcePosition p, bool j,
std::string n, ParameterList pl, std::string r)
: CallableNode(kind, p, n, pl, r, {}), javascript_linkage(j) {}
bool javascript_linkage;
std::string name;
ParameterList parameters;
std::string return_type;
Statement* body;
};
struct ExternalBuiltinDeclaration : Declaration {
struct ExternalBuiltinDeclaration : BuiltinDeclaration {
DEFINE_AST_NODE_LEAF_BOILERPLATE(ExternalBuiltinDeclaration)
ExternalBuiltinDeclaration(SourcePosition p, bool j, std::string n,
ParameterList pl, std::string r)
: Declaration(kKind, p),
javascript_linkage(j),
name(std::move(n)),
parameters(std::move(pl)),
return_type(std::move(r)) {}
bool javascript_linkage;
std::string name;
ParameterList parameters;
std::string return_type;
: BuiltinDeclaration(kKind, p, j, n, pl, r) {}
};
struct TorqueBuiltinDeclaration : BuiltinDeclaration {
DEFINE_AST_NODE_LEAF_BOILERPLATE(TorqueBuiltinDeclaration)
TorqueBuiltinDeclaration(SourcePosition p, bool j, std::string n,
ParameterList pl, std::string r)
: BuiltinDeclaration(kKind, p, j, n, pl, r) {}
};
struct ExternalRuntimeDeclaration : Declaration {
struct ExternalRuntimeDeclaration : CallableNode {
DEFINE_AST_NODE_LEAF_BOILERPLATE(ExternalRuntimeDeclaration)
ExternalRuntimeDeclaration(SourcePosition p, std::string n, ParameterList pl,
std::string r)
: CallableNode(kKind, p, n, pl, r, {}) {}
};
struct StandardDeclaration : Declaration {
DEFINE_AST_NODE_LEAF_BOILERPLATE(StandardDeclaration)
StandardDeclaration(SourcePosition p, CallableNode* c, Statement* b)
: Declaration(kKind, p), callable(c), body(b) {}
CallableNode* callable;
Statement* body;
};
struct GenericDeclaration : Declaration {
DEFINE_AST_NODE_LEAF_BOILERPLATE(GenericDeclaration)
GenericDeclaration(SourcePosition p, CallableNode* c,
std::vector<std::string> gp, Statement* b)
: Declaration(kKind, p),
callable(c),
generic_parameters(std::move(gp)),
body(b) {}
CallableNode* callable;
std::vector<std::string> generic_parameters;
Statement* body;
};
struct SpecializationDeclaration : Declaration {
DEFINE_AST_NODE_LEAF_BOILERPLATE(SpecializationDeclaration)
SpecializationDeclaration(SourcePosition p, std::string n,
std::vector<std::string> gp, ParameterList pl,
std::string r, LabelAndTypesVector l, Statement* b)
: Declaration(kKind, p),
name(std::move(n)),
parameters(std::move(pl)),
return_type(std::move(r)) {}
generic_parameters(gp),
signature(new CallableNodeSignature{pl, r, l}),
body(std::move(b)) {}
DEFINE_AST_NODE_INNER_BOILERPLATE(SpecializationDeclaration)
std::string name;
ParameterList parameters;
std::string return_type;
std::vector<std::string> generic_parameters;
std::unique_ptr<CallableNodeSignature> signature;
Statement* body;
};
struct ConstDeclaration : Declaration {
......
......@@ -9,6 +9,7 @@
#include <string>
#include "src/base/logging.h"
#include "src/torque/ast.h"
#include "src/torque/types.h"
#include "src/torque/utils.h"
......@@ -30,6 +31,8 @@ class Declarable {
kMacroList,
kBuiltin,
kRuntimeFunction,
kGeneric,
kTypeAlias,
kLabel,
kConstant
};
......@@ -39,6 +42,8 @@ class Declarable {
bool IsMacro() const { return kind() == kMacro; }
bool IsBuiltin() const { return kind() == kBuiltin; }
bool IsRuntimeFunction() const { return kind() == kRuntimeFunction; }
bool IsGeneric() const { return kind() == kGeneric; }
bool IsTypeAlias() const { return kind() == kTypeAlias; }
bool IsParameter() const { return kind() == kParameter; }
bool IsLabel() const { return kind() == kLabel; }
bool IsVariable() const { return kind() == kVariable; }
......@@ -296,9 +301,44 @@ class RuntimeFunction : public Callable {
: Callable(Declarable::kRuntimeFunction, name, signature) {}
};
class Generic : public Declarable {
public:
DECLARE_DECLARABLE_BOILERPLATE(Generic, generic);
GenericDeclaration* declaration() const { return declaration_; }
Module* module() const { return module_; }
private:
friend class Declarations;
Generic(const std::string& name, Module* module,
GenericDeclaration* declaration)
: Declarable(Declarable::kGeneric),
module_(module),
declaration_(declaration) {}
Module* module_;
GenericDeclaration* declaration_;
};
typedef std::pair<Generic*, TypeVector> SpecializationKey;
class TypeAlias : public Declarable {
public:
DECLARE_DECLARABLE_BOILERPLATE(TypeAlias, instantiated_type);
const Type* type() const { return type_; }
private:
friend class Declarations;
TypeAlias(const std::string& name, const Type* type)
: Declarable(Declarable::kTypeAlias), type_(type) {}
const Type* type_;
};
inline std::ostream& operator<<(std::ostream& os, const Callable& m) {
os << "macro " << m.signature().return_type << " " << m.name()
<< m.signature().parameter_types;
os << "callable " << m.name() << "(" << m.signature().parameter_types
<< "): " << m.signature().return_type;
return os;
}
......
This diff is collapsed.
This diff is collapsed.
......@@ -10,10 +10,25 @@ namespace internal {
namespace torque {
Scope* Declarations::GetNodeScope(const AstNode* node) {
auto i = node_scopes_.find(node);
if (i != node_scopes_.end()) return i->second;
std::pair<const AstNode*, TypeVector> key(
node, current_generic_specialization_ == nullptr
? TypeVector()
: current_generic_specialization_->second);
auto i = scopes_.find(key);
if (i != scopes_.end()) return i->second;
Scope* result = chain_.NewScope();
node_scopes_[node] = result;
scopes_[key] = result;
return result;
}
Scope* Declarations::GetGenericScope(Generic* generic,
const TypeVector& types) {
std::pair<const AstNode*, TypeVector> key(generic->declaration()->callable,
types);
auto i = scopes_.find(key);
if (i != scopes_.end()) return i->second;
Scope* result = chain_.NewScope();
scopes_[key] = result;
return result;
}
......@@ -32,13 +47,16 @@ void Declarations::CheckAlreadyDeclared(SourcePosition pos,
const Type* Declarations::LookupType(SourcePosition pos,
const std::string& name) {
Declarable* raw = Lookup(pos, name);
if (!raw->IsType()) {
std::stringstream s;
s << "declaration \"" << name << "\" is not a Type at "
<< PositionAsString(pos);
ReportError(s.str());
if (raw->IsType()) {
return Type::cast(raw);
} else if (raw->IsTypeAlias()) {
return TypeAlias::cast(raw)->type();
}
return Type::cast(raw);
std::stringstream s;
s << "declaration \"" << name << "\" is not a Type at "
<< PositionAsString(pos);
ReportError(s.str());
return nullptr;
}
Value* Declarations::LookupValue(SourcePosition pos, const std::string& name) {
......@@ -98,6 +116,21 @@ Builtin* Declarations::LookupBuiltin(SourcePosition pos,
return nullptr;
}
Generic* Declarations::LookupGeneric(const SourcePosition& pos,
const std::string& name) {
Declarable* declarable = Lookup(name);
if (declarable != nullptr) {
if (declarable->IsGeneric()) {
return Generic::cast(declarable);
}
ReportError(name + " referenced at " + PositionAsString(pos) +
" is not a generic");
}
ReportError(std::string("generic ") + name + " referenced at " +
PositionAsString(pos) + " is not defined");
return nullptr;
}
const Type* Declarations::DeclareType(SourcePosition pos,
const std::string& name,
const std::string& generated,
......@@ -126,6 +159,13 @@ const Type* Declarations::DeclareType(SourcePosition pos,
return result;
}
void Declarations::DeclareTypeAlias(SourcePosition pos, const std::string& name,
const Type* aliased_type) {
CheckAlreadyDeclared(pos, name, "aliased type");
TypeAlias* result = new TypeAlias(name, aliased_type);
Declare(name, std::unique_ptr<TypeAlias>(result));
}
Label* Declarations::DeclareLabel(SourcePosition pos, const std::string& name) {
CheckAlreadyDeclared(pos, name, "label");
Label* result = new Label(name);
......@@ -218,6 +258,24 @@ void Declarations::DeclareConstant(SourcePosition pos, const std::string& name,
Declare(name, std::unique_ptr<Declarable>(result));
}
Generic* Declarations::DeclareGeneric(SourcePosition pos,
const std::string& name, Module* module,
GenericDeclaration* generic) {
CheckAlreadyDeclared(pos, name, "generic");
Generic* result = new Generic(name, module, generic);
Declare(name, std::unique_ptr<Generic>(result));
generic_declaration_scopes_[result] = GetScopeChainSnapshot();
return result;
}
TypeVector Declarations::GetCurrentSpecializationTypeNamesVector() {
TypeVector result;
if (current_generic_specialization_ != nullptr) {
result = current_generic_specialization_->second;
}
return result;
}
} // namespace torque
} // namespace internal
} // namespace v8
......@@ -17,7 +17,9 @@ namespace torque {
class Declarations {
public:
explicit Declarations(SourceFileMap* source_file_map)
: source_file_map_(source_file_map), unique_declaration_number_(0) {}
: source_file_map_(source_file_map),
unique_declaration_number_(0),
current_generic_specialization_(nullptr) {}
Declarable* Lookup(const std::string& name) { return chain_.Lookup(name); }
......@@ -42,17 +44,22 @@ class Declarations {
Label* LookupLabel(SourcePosition pos, const std::string& name);
Generic* LookupGeneric(const SourcePosition& pos, const std::string& name);
const Type* DeclareType(SourcePosition pos, const std::string& name,
const std::string& generated,
const std::string* parent = nullptr);
void DeclareTypeAlias(SourcePosition pos, const std::string& name,
const Type* aliased_type);
Label* DeclareLabel(SourcePosition pos, const std::string& name);
Macro* DeclareMacro(SourcePosition pos, const std::string& name,
const Signature& signature);
Builtin* DeclareBuiltin(SourcePosition pos, const std::string& name,
Builtin::Kind kind, const Signature& signature);
const Builtin::Kind kind, const Signature& signature);
RuntimeFunction* DeclareRuntimeFunction(SourcePosition pos,
const std::string& name,
......@@ -70,6 +77,13 @@ class Declarations {
void DeclareConstant(SourcePosition pos, const std::string& name,
const Type* type, const std::string& value);
Generic* DeclareGeneric(SourcePosition pos, const std::string& name,
Module* module, GenericDeclaration* generic);
TypeVector GetCurrentSpecializationTypeNamesVector();
ScopeChain::Snapshot GetScopeChainSnapshot() { return chain_.TaskSnapshot(); }
std::set<const Variable*> GetLiveVariables() {
return chain_.GetLiveVariables();
}
......@@ -78,12 +92,17 @@ class Declarations {
return source_file_map_->PositionAsString(pos);
}
Statement* next_body() const { return next_body_; }
void PrintScopeChain() { chain_.Print(); }
class NodeScopeActivator;
class GenericScopeActivator;
class ScopedGenericInstantiation;
private:
Scope* GetNodeScope(const AstNode* node);
Scope* GetGenericScope(Generic* generic, const TypeVector& types);
void Declare(const std::string& name, std::unique_ptr<Declarable> d) {
Declarable* ptr = d.get();
......@@ -99,8 +118,11 @@ class Declarations {
SourceFileMap* source_file_map_;
int unique_declaration_number_;
ScopeChain chain_;
const SpecializationKey* current_generic_specialization_;
Statement* next_body_;
std::vector<std::unique_ptr<Declarable>> declarables_;
std::map<const AstNode*, Scope*> node_scopes_;
std::map<std::pair<const AstNode*, TypeVector>, Scope*> scopes_;
std::map<Generic*, ScopeChain::Snapshot> generic_declaration_scopes_;
};
class Declarations::NodeScopeActivator {
......@@ -112,6 +134,33 @@ class Declarations::NodeScopeActivator {
Scope::Activator activator_;
};
class Declarations::GenericScopeActivator {
public:
GenericScopeActivator(Declarations* declarations,
const SpecializationKey& key)
: activator_(declarations->GetGenericScope(key.first, key.second)) {}
private:
Scope::Activator activator_;
};
class Declarations::ScopedGenericInstantiation {
public:
ScopedGenericInstantiation(Declarations* declarations,
const SpecializationKey& key)
: declarations_(declarations),
restorer_(declarations->generic_declaration_scopes_[key.first]) {
declarations->current_generic_specialization_ = &key;
}
~ScopedGenericInstantiation() {
declarations_->current_generic_specialization_ = nullptr;
}
private:
Declarations* declarations_;
ScopeChain::ScopedSnapshotRestorer restorer_;
};
} // namespace torque
} // namespace internal
} // namespace v8
......
......@@ -10,23 +10,33 @@ namespace v8 {
namespace internal {
namespace torque {
Signature FileVisitor::MakeSignature(SourcePosition pos,
const ParameterList& parameters,
const std::string& return_type,
const LabelAndTypesVector& labels) {
Signature FileVisitor::MakeSignature(CallableNode* decl,
const CallableNodeSignature* signature) {
Declarations::NodeScopeActivator scope(declarations(), decl);
LabelDeclarationVector definition_vector;
for (auto label : labels) {
LabelDeclaration def = {label.name, GetTypeVector(pos, label.types)};
for (auto label : signature->labels) {
LabelDeclaration def = {label.name, GetTypeVector(decl->pos, label.types)};
definition_vector.push_back(def);
}
Signature result{
parameters.names,
{GetTypeVector(pos, parameters.types), parameters.has_varargs},
declarations()->LookupType(pos, return_type),
signature->parameters.names,
{GetTypeVector(decl->pos, signature->parameters.types),
signature->parameters.has_varargs},
declarations()->LookupType(decl->pos, signature->return_type),
definition_vector};
return result;
}
std::string FileVisitor::GetGeneratedCallableName(
const std::string& name, const TypeVector& specialized_types) {
std::string result = name;
for (auto type : specialized_types) {
result += std::to_string(type->name().size());
result += type->name();
}
return result;
}
Callable* FileVisitor::LookupCall(SourcePosition pos, const std::string& name,
const TypeVector& parameter_types) {
Callable* result = nullptr;
......@@ -57,6 +67,12 @@ Callable* FileVisitor::LookupCall(SourcePosition pos, const std::string& name,
<< PositionAsString(pos);
ReportError(stream.str());
}
} else {
std::stringstream stream;
stream << "can't call " << name << " because it's not callable"
<< ": call parameters were (" << parameter_types << ") at "
<< PositionAsString(pos);
ReportError(stream.str());
}
size_t caller_size = parameter_types.size();
......@@ -64,7 +80,7 @@ Callable* FileVisitor::LookupCall(SourcePosition pos, const std::string& name,
if (caller_size != callee_size &&
!result->signature().parameter_types.var_args) {
std::stringstream stream;
stream << "parameter count mismatch calling " << *result << ": expected "
stream << "parameter count mismatch calling " << *result << " - expected "
<< std::to_string(callee_size) << ", found "
<< std::to_string(caller_size);
ReportError(stream.str());
......@@ -73,6 +89,30 @@ Callable* FileVisitor::LookupCall(SourcePosition pos, const std::string& name,
return result;
}
void FileVisitor::QueueGenericSpecialization(
SpecializationKey key, CallableNode* callable,
const CallableNodeSignature* signature, Statement* body) {
pending_specializations_.push_back({key, callable, signature, body,
declarations()->GetScopeChainSnapshot()});
}
void FileVisitor::DrainSpecializationQueue() {
while (pending_specializations_.size() != 0) {
PendingSpecialization specialization(pending_specializations_.front());
pending_specializations_.pop_front();
if (completed_specializations_.find(specialization.key) ==
completed_specializations_.end()) {
Declarations::ScopedGenericInstantiation instantiation(
declarations(), specialization.key);
FileVisitor::ScopedModuleActivator activator(
this, specialization.key.first->module());
Specialize(specialization.key, specialization.callable,
specialization.signature, specialization.body);
completed_specializations_.insert(specialization.key);
}
}
}
} // namespace torque
} // namespace internal
} // namespace v8
......@@ -5,6 +5,7 @@
#ifndef V8_TORQUE_FILE_VISITOR_H_
#define V8_TORQUE_FILE_VISITOR_H_
#include <deque>
#include <string>
#include "src/torque/ast.h"
......@@ -37,6 +38,21 @@ class FileVisitor {
Ast* ast() { return global_context_.ast(); }
Declarations* declarations() { return global_context_.declarations(); }
void DrainSpecializationQueue();
class ScopedModuleActivator {
public:
ScopedModuleActivator(FileVisitor* visitor, Module* module)
: visitor_(visitor), saved_module_(visitor->CurrentModule()) {
visitor->module_ = module;
}
~ScopedModuleActivator() { visitor_->module_ = saved_module_; }
private:
FileVisitor* visitor_;
Module* saved_module_;
};
protected:
static constexpr const char* kTrueLabelName = "_True";
static constexpr const char* kFalseLabelName = "_False";
......@@ -47,6 +63,7 @@ class FileVisitor {
Module* CurrentModule() const { return module_; }
friend class ScopedModuleActivator;
TypeOracle& GetTypeOracle() { return global_context_.GetTypeOracle(); }
std::string GetParameterVariableFromName(const std::string& name) {
......@@ -60,12 +77,32 @@ class FileVisitor {
Callable* LookupCall(SourcePosition pos, const std::string& name,
const TypeVector& parameter_types);
Signature MakeSignature(SourcePosition pos, const ParameterList& parameters,
const std::string& return_type,
const LabelAndTypesVector& labels);
Signature MakeSignature(CallableNode* decl,
const CallableNodeSignature* signature);
std::string GetGeneratedCallableName(const std::string& name,
const TypeVector& specialized_types);
struct PendingSpecialization {
SpecializationKey key;
CallableNode* callable;
const CallableNodeSignature* signature;
Statement* body;
ScopeChain::Snapshot snapshot;
};
void QueueGenericSpecialization(SpecializationKey, CallableNode* callable,
const CallableNodeSignature* signature,
Statement* body);
virtual void Specialize(const SpecializationKey&, CallableNode* callable,
const CallableNodeSignature* signature,
Statement* body) = 0;
GlobalContext& global_context_;
Declarations* declarations_;
std::deque<PendingSpecialization> pending_specializations_;
std::set<SpecializationKey> completed_specializations_;
Callable* current_callable_;
Module* module_;
};
......
......@@ -81,19 +81,25 @@ class GlobalContext {
bool verbose() const { return verbose_; }
void AddControlSplitChangedVariables(const AstNode* node,
const TypeVector& specialization_types,
const std::set<const Variable*>& vars) {
control_split_changed_variables_[node] = vars;
auto key = std::make_pair(node, specialization_types);
control_split_changed_variables_[key] = vars;
}
const std::set<const Variable*>& GetControlSplitChangedVariables(
const AstNode* node) {
assert(control_split_changed_variables_.find(node) !=
const AstNode* node, const TypeVector& specialization_types) {
auto key = std::make_pair(node, specialization_types);
assert(control_split_changed_variables_.find(key) !=
control_split_changed_variables_.end());
return control_split_changed_variables_.find(node)->second;
return control_split_changed_variables_.find(key)->second;
}
void MarkVariableChanged(const AstNode* node, Variable* var) {
control_split_changed_variables_[node].insert(var);
void MarkVariableChanged(const AstNode* node,
const TypeVector& specialization_types,
Variable* var) {
auto key = std::make_pair(node, specialization_types);
control_split_changed_variables_[key].insert(var);
}
friend class CurrentCallableActivator;
......@@ -120,12 +126,12 @@ class GlobalContext {
bool verbose_;
int next_label_number_;
Declarations declarations_;
Callable* current_callable_;
std::vector<std::pair<Label*, Label*>> break_continue_stack_;
TypeOracle type_oracle_;
std::map<std::string, std::unique_ptr<Module>> modules_;
Module* default_module_;
std::vector<std::pair<Label*, Label*>> break_continue_stack_;
Callable* current_callable_;
std::map<const AstNode*, std::set<const Variable*>>
std::map<std::pair<const AstNode*, TypeVector>, std::set<const Variable*>>
control_split_changed_variables_;
Ast ast_;
};
......@@ -133,14 +139,18 @@ class GlobalContext {
class CurrentCallableActivator {
public:
CurrentCallableActivator(GlobalContext& context, Callable* callable,
Declaration* decl)
CallableNode* decl)
: context_(context), scope_activator_(context.declarations(), decl) {
remembered_callable_ = context_.current_callable_;
context_.current_callable_ = callable;
}
~CurrentCallableActivator() { context_.current_callable_ = nullptr; }
~CurrentCallableActivator() {
context_.current_callable_ = remembered_callable_;
}
private:
GlobalContext& context_;
Callable* remembered_callable_;
Declarations::NodeScopeActivator scope_activator_;
};
......
......@@ -49,6 +49,19 @@ void ImplementationVisitor::Visit(Declaration* decl) {
}
}
void ImplementationVisitor::Visit(CallableNode* decl,
const Signature& signature, Statement* body) {
switch (decl->kind) {
#define ENUM_ITEM(name) \
case AstNode::Kind::k##name: \
return Visit(name::cast(decl), signature, body);
AST_CALLABLE_NODE_KIND_LIST(ENUM_ITEM)
#undef ENUM_ITEM
default:
UNIMPLEMENTED();
}
}
void ImplementationVisitor::Visit(ModuleDeclaration* decl) {
Module* module = decl->GetModule();
......@@ -120,6 +133,8 @@ void ImplementationVisitor::Visit(ModuleDeclaration* decl) {
for (auto& child : decl->declarations) Visit(child);
module_ = saved_module;
DrainSpecializationQueue();
source << "} // namepsace internal" << std::endl
<< "} // namespace v8" << std::endl
<< "" << std::endl;
......@@ -131,11 +146,13 @@ void ImplementationVisitor::Visit(ModuleDeclaration* decl) {
header << "#endif // " << headerDefine << std::endl;
}
void ImplementationVisitor::Visit(MacroDeclaration* decl) {
Signature signature = MakeSignature(decl->pos, decl->parameters,
decl->return_type, decl->labels);
void ImplementationVisitor::Visit(TorqueMacroDeclaration* decl,
const Signature& sig, Statement* body) {
Signature signature = MakeSignature(decl, decl->signature.get());
std::string name = GetGeneratedCallableName(
decl->name, declarations()->GetCurrentSpecializationTypeNamesVector());
const TypeVector& list = signature.types();
Macro* macro = declarations()->LookupMacro(decl->pos, decl->name, list);
Macro* macro = declarations()->LookupMacro(decl->pos, name, list);
CurrentCallableActivator activator(global_context_, macro, decl);
......@@ -167,7 +184,7 @@ void ImplementationVisitor::Visit(MacroDeclaration* decl) {
Label* macro_end = declarations()->DeclareLabel(decl->pos, "macro_end");
GenerateLabelDefinition(macro_end, decl);
const Type* result = Visit(decl->body);
const Type* result = Visit(body);
if (result->IsNever()) {
if (!macro->signature().return_type->IsNever() && !macro->HasReturns()) {
std::stringstream s;
......@@ -206,15 +223,18 @@ void ImplementationVisitor::Visit(MacroDeclaration* decl) {
source_out() << "}" << std::endl << std::endl;
}
void ImplementationVisitor::Visit(BuiltinDeclaration* decl) {
source_out() << "TF_BUILTIN(" << decl->name << ", "
void ImplementationVisitor::Visit(TorqueBuiltinDeclaration* decl,
const Signature& signature, Statement* body) {
std::string name = GetGeneratedCallableName(
decl->name, declarations()->GetCurrentSpecializationTypeNamesVector());
source_out() << "TF_BUILTIN(" << name << ", "
<< GetDSLAssemblerName(CurrentModule()) << ") {" << std::endl;
Builtin* builtin = declarations()->LookupBuiltin(decl->pos, decl->name);
Builtin* builtin = declarations()->LookupBuiltin(decl->pos, name);
CurrentCallableActivator activator(global_context_, builtin, decl);
// Context
const Value* val =
declarations()->LookupValue(decl->pos, decl->parameters.names[0]);
const Value* val = declarations()->LookupValue(
decl->pos, decl->signature->parameters.names[0]);
GenerateIndent();
source_out() << "TNode<Context> " << val->GetValueForDeclaration()
<< " = UncheckedCast<Context>(Parameter("
......@@ -225,9 +245,9 @@ void ImplementationVisitor::Visit(BuiltinDeclaration* decl) {
size_t first = 1;
if (builtin->IsVarArgsJavaScript()) {
assert(decl->parameters.has_varargs);
assert(decl->signature->parameters.has_varargs);
Constant* arguments = Constant::cast(declarations()->LookupValue(
decl->pos, decl->parameters.arguments_variable));
decl->pos, decl->signature->parameters.arguments_variable));
std::string arguments_name = arguments->GetValueForDeclaration();
GenerateIndent();
source_out()
......@@ -237,8 +257,8 @@ void ImplementationVisitor::Visit(BuiltinDeclaration* decl) {
source_out() << "CodeStubArguments arguments_impl(this, "
"ChangeInt32ToIntPtr(argc));"
<< std::endl;
const Value* receiver =
declarations()->LookupValue(decl->pos, decl->parameters.names[1]);
const Value* receiver = declarations()->LookupValue(
decl->pos, decl->signature->parameters.names[1]);
GenerateIndent();
source_out() << "TNode<Object> " << receiver->GetValueForDeclaration()
<< " = arguments_impl.GetReceiver();" << std::endl;
......@@ -252,8 +272,8 @@ void ImplementationVisitor::Visit(BuiltinDeclaration* decl) {
first = 2;
}
GenerateParameterList(decl->pos, decl->parameters.names, first);
Visit(decl->body);
GenerateParameterList(decl->pos, decl->signature->parameters.names, first);
Visit(body);
source_out() << "}" << std::endl << std::endl;
}
......@@ -1082,7 +1102,8 @@ VisitResult ImplementationVisitor::GenerateOperation(
void ImplementationVisitor::GenerateChangedVarsFromControlSplit(AstNode* node) {
const std::set<const Variable*>& changed_vars =
global_context_.GetControlSplitChangedVariables(node);
global_context_.GetControlSplitChangedVariables(
node, declarations()->GetCurrentSpecializationTypeNamesVector());
source_out() << "{";
bool first = true;
for (auto v : changed_vars) {
......@@ -1206,7 +1227,9 @@ Variable* ImplementationVisitor::GenerateVariableDeclaration(
// assumed that it changes along all control split paths because it's no
// longer possible to run the control-flow anlaysis in the declaration pass
// over the variable.
global_context_.MarkVariableChanged(node, variable);
global_context_.MarkVariableChanged(
node, declarations()->GetCurrentSpecializationTypeNamesVector(),
variable);
}
GenerateIndent();
......@@ -1376,9 +1399,33 @@ VisitResult ImplementationVisitor::GenerateCall(
return VisitResult(result_type, result_variable_name);
}
void ImplementationVisitor::Visit(StandardDeclaration* decl) {
Visit(decl->callable, {}, decl->body);
}
void ImplementationVisitor::Visit(SpecializationDeclaration* decl) {
Generic* generic = declarations()->LookupGeneric(decl->pos, decl->name);
TypeVector specialization_types =
GetTypeVector(decl->pos, decl->generic_parameters);
CallableNode* callable = generic->declaration()->callable;
QueueGenericSpecialization({generic, specialization_types}, callable,
decl->signature.get(), decl->body);
}
VisitResult ImplementationVisitor::Visit(CallExpression* expr,
bool is_tailcall) {
Arguments arguments;
std::string name = expr->callee;
if (expr->generic_arguments.size() != 0) {
Generic* generic = declarations()->LookupGeneric(expr->pos, expr->callee);
TypeVector specialization_types =
GetTypeVector(expr->pos, expr->generic_arguments);
name = GetGeneratedCallableName(name, specialization_types);
CallableNode* callable = generic->declaration()->callable;
QueueGenericSpecialization({generic, specialization_types}, callable,
callable->signature.get(),
generic->declaration()->body);
}
for (Expression* arg : expr->arguments)
arguments.parameters.push_back(Visit(arg));
arguments.labels = LabelsFromIdentifiers(expr->pos, expr->labels);
......@@ -1388,10 +1435,9 @@ VisitResult ImplementationVisitor::Visit(CallExpression* expr,
s << "can't tail call an operator" << PositionAsString(expr->pos);
ReportError(s.str());
}
return GenerateOperation(expr->pos, expr->callee, arguments);
return GenerateOperation(expr->pos, name, arguments);
}
VisitResult result =
GenerateCall(expr->pos, expr->callee, arguments, is_tailcall);
VisitResult result = GenerateCall(expr->pos, name, arguments, is_tailcall);
if (!result.type()->IsVoidOrNever()) {
GenerateIndent();
source_out() << "USE(" << result.variable() << ");" << std::endl;
......
......@@ -96,13 +96,23 @@ class ImplementationVisitor : public FileVisitor {
void Visit(ExplicitModuleDeclaration* decl) {
Visit(implicit_cast<ModuleDeclaration*>(decl));
}
void Visit(MacroDeclaration* decl);
void Visit(BuiltinDeclaration* decl);
void Visit(TypeDeclaration* decl) {}
void Visit(ConstDeclaration* decl) {}
void Visit(ExternalMacroDeclaration* decl) {}
void Visit(ExternalBuiltinDeclaration* decl) {}
void Visit(ExternalRuntimeDeclaration* decl) {}
void Visit(StandardDeclaration* decl);
void Visit(GenericDeclaration* decl) {}
void Visit(SpecializationDeclaration* decl);
void Visit(TorqueMacroDeclaration* decl, const Signature& signature,
Statement* body);
void Visit(TorqueBuiltinDeclaration* decl, const Signature& signature,
Statement* body);
void Visit(ExternalMacroDeclaration* decl, const Signature& signature,
Statement* body) {}
void Visit(ExternalBuiltinDeclaration* decl, const Signature& signature,
Statement* body) {}
void Visit(ExternalRuntimeDeclaration* decl, const Signature& signature,
Statement* body) {}
void Visit(CallableNode* decl, const Signature& signature, Statement* body);
VisitResult Visit(CallExpression* expr, bool is_tail = false);
const Type* Visit(TailCallStatement* stmt);
......@@ -217,6 +227,13 @@ class ImplementationVisitor : public FileVisitor {
const Type* destination_type,
VisitResult source);
void Specialize(const SpecializationKey& key, CallableNode* callable,
const CallableNodeSignature* signature,
Statement* body) override {
Declarations::GenericScopeActivator scope(declarations(), key);
Visit(callable, MakeSignature(callable, signature), body);
}
std::string NewTempVariable();
std::string GenerateNewTempVariable(const Type* type);
......
......@@ -118,8 +118,30 @@ class ScopeChain {
}
}
struct Snapshot {
ScopeChain* chain;
std::vector<Scope*> current_scopes;
};
Snapshot TaskSnapshot() { return {this, current_scopes_}; }
class ScopedSnapshotRestorer {
public:
explicit ScopedSnapshotRestorer(const Snapshot& snapshot)
: chain_(snapshot.chain) {
saved_ = chain_->current_scopes_;
chain_->current_scopes_ = snapshot.current_scopes;
}
~ScopedSnapshotRestorer() { chain_->current_scopes_ = saved_; }
private:
ScopeChain* chain_;
std::vector<Scope*> saved_;
};
private:
friend class Scope;
friend class ScopedSnapshotRestorer;
int GetNextScopeNumber() { return next_scope_number_++; }
......
......@@ -101,6 +101,29 @@ TEST(TestPartiallyUnusedLabel) {
ft.CheckCall(ft.true_value());
}
TEST(TestBuiltinSpecialization) {
Isolate* isolate(CcTest::InitIsolateOnce());
CodeAssemblerTester asm_tester(isolate, 0);
TestBuiltinsFromDSLAssembler m(asm_tester.state());
{
Node* temp = m.SmiConstant(0);
m.TestBuiltinSpecialization(m.UncheckedCast<Context>(temp));
m.Return(m.UndefinedConstant());
}
FunctionTester ft(asm_tester.GenerateCode(), 0);
}
TEST(TestMacroSpecialization) {
Isolate* isolate(CcTest::InitIsolateOnce());
CodeAssemblerTester asm_tester(isolate, 0);
TestBuiltinsFromDSLAssembler m(asm_tester.state());
{
m.TestMacroSpecialization();
m.Return(m.UndefinedConstant());
}
FunctionTester ft(asm_tester.GenerateCode(), 0);
}
} // namespace compiler
} // namespace internal
} // namespace v8
......@@ -3,108 +3,159 @@
// found in the LICENSE file.
module test {
macro ElementsKindTestHelper1(kind: constexpr ElementsKind): bool {
if constexpr ((kind == UINT8_ELEMENTS) || (kind == UINT16_ELEMENTS)) {
return true;
}
else {
return false;
}
}
macro ElementsKindTestHelper1(kind: constexpr ElementsKind): bool {
if constexpr ((kind == UINT8_ELEMENTS) || (kind == UINT16_ELEMENTS)) {
return true;
} else {
return false;
macro ElementsKindTestHelper2(kind: constexpr ElementsKind): bool {
return ((kind == UINT8_ELEMENTS) || (kind == UINT16_ELEMENTS));
}
}
macro ElementsKindTestHelper2(kind: constexpr ElementsKind): bool {
return ((kind == UINT8_ELEMENTS) || (kind == UINT16_ELEMENTS));
}
macro ElementsKindTestHelper3(kind: constexpr ElementsKind): constexpr bool {
return ((kind == UINT8_ELEMENTS) || (kind == UINT16_ELEMENTS));
}
macro ElementsKindTestHelper3(kind: constexpr ElementsKind): constexpr bool {
return ((kind == UINT8_ELEMENTS) || (kind == UINT16_ELEMENTS));
}
macro LabelTestHelper1(): never
labels Label1 {
goto Label1;
}
macro LabelTestHelper1(): never
labels Label1 {
goto Label1;
}
macro LabelTestHelper2(): never
labels Label2(Smi) {
goto Label2(42);
}
macro LabelTestHelper2(): never
labels Label2(Smi) {
goto Label2(42);
}
macro LabelTestHelper3(): never
labels Label3(String, Smi) {
goto Label3('foo', 7);
}
macro LabelTestHelper3(): never
labels Label3(String, Smi) {
goto Label3('foo', 7);
}
macro TestConstexpr1() {
assert(convert<bool>(IsFastElementsKind(PACKED_SMI_ELEMENTS)));
}
macro TestConstexpr1() {
assert(convert<bool>(IsFastElementsKind(PACKED_SMI_ELEMENTS)));
}
macro TestConstexprIf() {
assert(ElementsKindTestHelper1(UINT8_ELEMENTS));
assert(ElementsKindTestHelper1(UINT16_ELEMENTS));
assert(!ElementsKindTestHelper1(UINT32_ELEMENTS));
}
macro TestConstexprIf() {
assert(ElementsKindTestHelper1(UINT8_ELEMENTS));
assert(ElementsKindTestHelper1(UINT16_ELEMENTS));
assert(!ElementsKindTestHelper1(UINT32_ELEMENTS));
}
macro TestConstexprReturn() {
assert(convert<bool>(ElementsKindTestHelper3(UINT8_ELEMENTS)));
assert(convert<bool>(ElementsKindTestHelper3(UINT16_ELEMENTS)));
assert(!convert<bool>(ElementsKindTestHelper3(UINT32_ELEMENTS)));
assert(convert<bool>(!ElementsKindTestHelper3(UINT32_ELEMENTS)));
}
macro TestConstexprReturn() {
assert(convert<bool>(ElementsKindTestHelper3(UINT8_ELEMENTS)));
assert(convert<bool>(ElementsKindTestHelper3(UINT16_ELEMENTS)));
assert(!convert<bool>(ElementsKindTestHelper3(UINT32_ELEMENTS)));
assert(convert<bool>(!ElementsKindTestHelper3(UINT32_ELEMENTS)));
}
macro TestGotoLabel(): Boolean {
try {
LabelTestHelper1() otherwise Label1;
}
label Label1 {
return True;
}
}
macro TestGotoLabel(): Boolean {
try {
LabelTestHelper1() otherwise Label1;
macro TestGotoLabelWithOneParameter(): Boolean {
try {
LabelTestHelper2() otherwise Label2;
}
label Label2(smi: Smi) {
assert(smi == 42);
return True;
}
}
label Label1 {
return True;
macro TestGotoLabelWithTwoParameters(): Boolean {
try {
LabelTestHelper3() otherwise Label3;
}
label Label3(str: String, smi: Smi) {
assert(str == 'foo');
assert(smi == 7);
return True;
}
}
}
macro TestGotoLabelWithOneParameter(): Boolean {
try {
LabelTestHelper2() otherwise Label2;
builtin GenericBuiltinTest<T: type>(c: Context, param: T): Object {
return Null;
}
label Label2(smi: Smi) {
assert(smi == 42);
return True;
GenericBuiltinTest<Object>(c: Context, param: Object): Object {
return param;
}
}
macro TestGotoLabelWithTwoParameters(): Boolean {
try {
LabelTestHelper3() otherwise Label3;
macro TestBuiltinSpecialization(c: Context) {
assert(GenericBuiltinTest<Smi>(c, 0) == Null);
assert(GenericBuiltinTest<Smi>(c, 1) == Null);
assert(GenericBuiltinTest<Object>(c, Undefined) == Undefined);
assert(GenericBuiltinTest<Object>(c, Undefined) == Undefined);
}
label Label3(str: String, smi: Smi) {
assert(str == 'foo');
assert(smi == 7);
return True;
macro LabelTestHelper4(flag: constexpr bool): never labels Label4, Label5 {
if constexpr (flag) goto Label4;
else
goto Label5;
}
}
macro LabelTestHelper4(flag: constexpr bool): never labels Label4, Label5 {
if constexpr (flag) goto Label4;
else goto Label5;
}
macro CallLabelTestHelper4(flag: constexpr bool): bool {
try {
LabelTestHelper4(flag) otherwise Label4, Label5;
}
label Label4 {
return true;
}
label Label5 {
return false;
}
}
macro CallLabelTestHelper4(flag: constexpr bool): bool {
try {
LabelTestHelper4(flag) otherwise Label4, Label5;
macro TestPartiallyUnusedLabel(): Boolean {
let r1: bool = CallLabelTestHelper4(true);
let r2: bool = CallLabelTestHelper4(false);
if (r1 && !r2)
return True;
else
return False;
}
label Label4 {
return true;
macro GenericMacroTest<T: type>(param: T): Object {
return Undefined;
}
label Label5 {
return false;
GenericMacroTest<Object>(param2: Object): Object {
return param2;
}
}
macro TestPartiallyUnusedLabel(): Boolean {
let r1: bool = CallLabelTestHelper4(true);
let r2: bool = CallLabelTestHelper4(false);
macro GenericMacroTestWithLabels<T: type>(param: T): Object labels X {
return Undefined;
}
if (r1 && !r2) return True;
else return False;
}
GenericMacroTestWithLabels<Object>(param2: Object): Object labels Y {
return param2;
}
macro TestMacroSpecialization() {
try {
if (True == False) goto Fail; // Silence warnings in release build
assert(GenericMacroTest<Smi>(0) == Undefined);
assert(GenericMacroTest<Smi>(1) == Undefined);
assert(GenericMacroTest<Object>(Null) == Null);
assert(GenericMacroTest<Object>(False) == False);
assert(GenericMacroTest<Object>(True) == True);
assert(GenericMacroTestWithLabels<Smi>(0) otherwise Fail == Undefined);
assert(GenericMacroTestWithLabels<Smi>(0) otherwise Fail == Undefined);
assert(GenericMacroTestWithLabels<Object>(Null) otherwise Fail == Null);
assert(GenericMacroTestWithLabels<Object>(False) otherwise Fail == False);
}
label Fail {
unreachable;
}
}
}
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