Commit 07f19a08 authored by Tobias Tebbi's avatar Tobias Tebbi Committed by Commit Bot

[torque] implement function pointers to builtins

This CL adds the new type expression
builtin(Context, ArgType1, ...) => ReturnType
and allows to use Torque-defined builtins as values of this type, as well
as calling values of this type.
The new function pointer types are subtypes of Code.

Change-Id: Ib7ba3ce6ef7a8591a4c79230dd189fd25698d5b9
Reviewed-on: https://chromium-review.googlesource.com/1060056
Commit-Queue: Tobias Tebbi <tebbi@chromium.org>
Reviewed-by: 's avatarDaniel Clifford <danno@chromium.org>
Cr-Commit-Position: refs/heads/master@{#53217}
parent f651409f
......@@ -17,6 +17,8 @@ type RawPtr generates 'TNode<RawPtrT>' constexpr 'void*';
type Number extends Object generates 'TNode<Number>';
type Smi extends Number generates 'TNode<Smi>';
type HeapObject extends Object generates 'TNode<HeapObject>';
type AbstractCode extends HeapObject generates 'TNode<AbstractCode>';
type Code extends AbstractCode generates 'TNode<Code>';
type JSReceiver extends HeapObject generates 'TNode<JSReceiver>';
type Context extends HeapObject generates 'TNode<Context>';
type String extends HeapObject generates 'TNode<String>';
......
......@@ -117,16 +117,18 @@ DECIMAL_LITERAL
| MINUS? DECIMAL_INTEGER_LITERAL EXPONENT_PART?
;
type : CONSTEXPR? IDENTIFIER;
typeList : '(' type? (',' type)* ')';
optionalGenericSpecializationTypeList: ('<' IDENTIFIER (',' IDENTIFIER)* '>')?;
type : CONSTEXPR? IDENTIFIER
| BUILTIN '(' typeList ')' '=>' type
;
typeList : (type (',' type)*)?;
genericSpecializationTypeList: '<' typeList '>';
optionalGenericTypeList: ('<' IDENTIFIER ':' 'type' (',' IDENTIFIER ':' 'type')* '>')?;
typeListMaybeVarArgs: '(' type? (',' type)* (',' VARARGS)? ')'
| '(' VARARGS ')';
labelParameter: IDENTIFIER typeList?;
labelParameter: IDENTIFIER ( '(' typeList ')' )?;
optionalType: (':' type)?;
optionalLabelList: (LABELS labelParameter (',' labelParameter)*)?;
......@@ -223,7 +225,7 @@ forOfLoop: FOR '(' variableDeclaration 'of' expression forOfRange ')' statementB
argument: expression;
argumentList: '(' argument? (',' argument)* ')';
helperCall: (MIN | MAX | IDENTIFIER) optionalGenericSpecializationTypeList argumentList optionalOtherwise;
helperCall: (MIN | MAX | IDENTIFIER) genericSpecializationTypeList? argumentList optionalOtherwise;
labelReference: IDENTIFIER;
variableDeclaration: LET IDENTIFIER ':' type;
......@@ -269,11 +271,11 @@ generatesDeclaration: 'generates' STRING_LITERAL;
constexprDeclaration: 'constexpr' STRING_LITERAL;
typeDeclaration : 'type' IDENTIFIER extendsDeclaration? generatesDeclaration? constexprDeclaration?';';
externalBuiltin : EXTERN JAVASCRIPT? BUILTIN IDENTIFIER optionalGenericTypeList typeList optionalType ';';
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;
genericSpecialization: IDENTIFIER genericSpecializationTypeList parameterList optionalType optionalLabelList helperBody;
macroDeclaration : MACRO IDENTIFIER optionalGenericTypeList parameterList optionalType optionalLabelList helperBody;
constDeclaration : 'const' IDENTIFIER ':' type '=' STRING_LITERAL ';';
......
......@@ -24,12 +24,10 @@ 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 enterGenericSpecializationTypeList(
TorqueParser::GenericSpecializationTypeListContext* /*ctx*/) override {}
void exitGenericSpecializationTypeList(
TorqueParser::GenericSpecializationTypeListContext* /*ctx*/) override {}
void enterOptionalGenericTypeList(
TorqueParser::OptionalGenericTypeListContext* /*ctx*/) override {}
......
......@@ -26,9 +26,8 @@ class TorqueBaseVisitor : public TorqueVisitor {
return visitChildren(ctx);
}
antlrcpp::Any visitOptionalGenericSpecializationTypeList(
TorqueParser::OptionalGenericSpecializationTypeListContext* ctx)
override {
antlrcpp::Any visitGenericSpecializationTypeList(
TorqueParser::GenericSpecializationTypeListContext* ctx) override {
return visitChildren(ctx);
}
......
This diff is collapsed.
......@@ -33,68 +33,69 @@ class TorqueLexer : public antlr4::Lexer {
T__17 = 18,
T__18 = 19,
T__19 = 20,
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,
ASSIGNMENT = 51,
ASSIGNMENT_OPERATOR = 52,
EQUAL = 53,
PLUS = 54,
MINUS = 55,
MULTIPLY = 56,
DIVIDE = 57,
MODULO = 58,
BIT_OR = 59,
BIT_AND = 60,
BIT_NOT = 61,
MAX = 62,
MIN = 63,
NOT_EQUAL = 64,
LESS_THAN = 65,
LESS_THAN_EQUAL = 66,
GREATER_THAN = 67,
GREATER_THAN_EQUAL = 68,
SHIFT_LEFT = 69,
SHIFT_RIGHT = 70,
SHIFT_RIGHT_ARITHMETIC = 71,
VARARGS = 72,
EQUALITY_OPERATOR = 73,
INCREMENT = 74,
DECREMENT = 75,
NOT = 76,
STRING_LITERAL = 77,
IDENTIFIER = 78,
WS = 79,
BLOCK_COMMENT = 80,
LINE_COMMENT = 81,
DECIMAL_LITERAL = 82
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,
EXTERN = 48,
ASSERT = 49,
UNREACHABLE_TOKEN = 50,
DEBUG_TOKEN = 51,
ASSIGNMENT = 52,
ASSIGNMENT_OPERATOR = 53,
EQUAL = 54,
PLUS = 55,
MINUS = 56,
MULTIPLY = 57,
DIVIDE = 58,
MODULO = 59,
BIT_OR = 60,
BIT_AND = 61,
BIT_NOT = 62,
MAX = 63,
MIN = 64,
NOT_EQUAL = 65,
LESS_THAN = 66,
LESS_THAN_EQUAL = 67,
GREATER_THAN = 68,
GREATER_THAN_EQUAL = 69,
SHIFT_LEFT = 70,
SHIFT_RIGHT = 71,
SHIFT_RIGHT_ARITHMETIC = 72,
VARARGS = 73,
EQUALITY_OPERATOR = 74,
INCREMENT = 75,
DECREMENT = 76,
NOT = 77,
STRING_LITERAL = 78,
IDENTIFIER = 79,
WS = 80,
BLOCK_COMMENT = 81,
LINE_COMMENT = 82,
DECIMAL_LITERAL = 83
};
explicit TorqueLexer(antlr4::CharStream* input);
......
......@@ -23,10 +23,10 @@ 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 enterGenericSpecializationTypeList(
TorqueParser::GenericSpecializationTypeListContext* ctx) = 0;
virtual void exitGenericSpecializationTypeList(
TorqueParser::GenericSpecializationTypeListContext* ctx) = 0;
virtual void enterOptionalGenericTypeList(
TorqueParser::OptionalGenericTypeListContext* ctx) = 0;
......
This source diff could not be displayed because it is too large. You can view the blob instead.
......@@ -33,74 +33,75 @@ class TorqueParser : public antlr4::Parser {
T__17 = 18,
T__18 = 19,
T__19 = 20,
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,
ASSIGNMENT = 51,
ASSIGNMENT_OPERATOR = 52,
EQUAL = 53,
PLUS = 54,
MINUS = 55,
MULTIPLY = 56,
DIVIDE = 57,
MODULO = 58,
BIT_OR = 59,
BIT_AND = 60,
BIT_NOT = 61,
MAX = 62,
MIN = 63,
NOT_EQUAL = 64,
LESS_THAN = 65,
LESS_THAN_EQUAL = 66,
GREATER_THAN = 67,
GREATER_THAN_EQUAL = 68,
SHIFT_LEFT = 69,
SHIFT_RIGHT = 70,
SHIFT_RIGHT_ARITHMETIC = 71,
VARARGS = 72,
EQUALITY_OPERATOR = 73,
INCREMENT = 74,
DECREMENT = 75,
NOT = 76,
STRING_LITERAL = 77,
IDENTIFIER = 78,
WS = 79,
BLOCK_COMMENT = 80,
LINE_COMMENT = 81,
DECIMAL_LITERAL = 82
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,
EXTERN = 48,
ASSERT = 49,
UNREACHABLE_TOKEN = 50,
DEBUG_TOKEN = 51,
ASSIGNMENT = 52,
ASSIGNMENT_OPERATOR = 53,
EQUAL = 54,
PLUS = 55,
MINUS = 56,
MULTIPLY = 57,
DIVIDE = 58,
MODULO = 59,
BIT_OR = 60,
BIT_AND = 61,
BIT_NOT = 62,
MAX = 63,
MIN = 64,
NOT_EQUAL = 65,
LESS_THAN = 66,
LESS_THAN_EQUAL = 67,
GREATER_THAN = 68,
GREATER_THAN_EQUAL = 69,
SHIFT_LEFT = 70,
SHIFT_RIGHT = 71,
SHIFT_RIGHT_ARITHMETIC = 72,
VARARGS = 73,
EQUALITY_OPERATOR = 74,
INCREMENT = 75,
DECREMENT = 76,
NOT = 77,
STRING_LITERAL = 78,
IDENTIFIER = 79,
WS = 80,
BLOCK_COMMENT = 81,
LINE_COMMENT = 82,
DECIMAL_LITERAL = 83
};
enum {
RuleType = 0,
RuleTypeList = 1,
RuleOptionalGenericSpecializationTypeList = 2,
RuleGenericSpecializationTypeList = 2,
RuleOptionalGenericTypeList = 3,
RuleTypeListMaybeVarArgs = 4,
RuleLabelParameter = 5,
......@@ -182,7 +183,7 @@ class TorqueParser : public antlr4::Parser {
class TypeContext;
class TypeListContext;
class OptionalGenericSpecializationTypeListContext;
class GenericSpecializationTypeListContext;
class OptionalGenericTypeListContext;
class TypeListMaybeVarArgsContext;
class LabelParameterContext;
......@@ -256,6 +257,9 @@ class TorqueParser : public antlr4::Parser {
size_t getRuleIndex() const override;
antlr4::tree::TerminalNode* IDENTIFIER();
antlr4::tree::TerminalNode* CONSTEXPR();
antlr4::tree::TerminalNode* BUILTIN();
TypeListContext* typeList();
TypeContext* type();
void enterRule(antlr4::tree::ParseTreeListener* listener) override;
void exitRule(antlr4::tree::ParseTreeListener* listener) override;
......@@ -280,14 +284,13 @@ class TorqueParser : public antlr4::Parser {
TypeListContext* typeList();
class OptionalGenericSpecializationTypeListContext
class GenericSpecializationTypeListContext
: public antlr4::ParserRuleContext {
public:
OptionalGenericSpecializationTypeListContext(
antlr4::ParserRuleContext* parent, size_t invokingState);
GenericSpecializationTypeListContext(antlr4::ParserRuleContext* parent,
size_t invokingState);
size_t getRuleIndex() const override;
std::vector<antlr4::tree::TerminalNode*> IDENTIFIER();
antlr4::tree::TerminalNode* IDENTIFIER(size_t i);
TypeListContext* typeList();
void enterRule(antlr4::tree::ParseTreeListener* listener) override;
void exitRule(antlr4::tree::ParseTreeListener* listener) override;
......@@ -295,8 +298,7 @@ class TorqueParser : public antlr4::Parser {
antlrcpp::Any accept(antlr4::tree::ParseTreeVisitor* visitor) override;
};
OptionalGenericSpecializationTypeListContext*
optionalGenericSpecializationTypeList();
GenericSpecializationTypeListContext* genericSpecializationTypeList();
class OptionalGenericTypeListContext : public antlr4::ParserRuleContext {
public:
......@@ -857,13 +859,12 @@ class TorqueParser : public antlr4::Parser {
public:
HelperCallContext(antlr4::ParserRuleContext* parent, size_t invokingState);
size_t getRuleIndex() const override;
OptionalGenericSpecializationTypeListContext*
optionalGenericSpecializationTypeList();
ArgumentListContext* argumentList();
OptionalOtherwiseContext* optionalOtherwise();
antlr4::tree::TerminalNode* MIN();
antlr4::tree::TerminalNode* MAX();
antlr4::tree::TerminalNode* IDENTIFIER();
GenericSpecializationTypeListContext* genericSpecializationTypeList();
void enterRule(antlr4::tree::ParseTreeListener* listener) override;
void exitRule(antlr4::tree::ParseTreeListener* listener) override;
......@@ -1347,8 +1348,7 @@ class TorqueParser : public antlr4::Parser {
size_t invokingState);
size_t getRuleIndex() const override;
antlr4::tree::TerminalNode* IDENTIFIER();
OptionalGenericSpecializationTypeListContext*
optionalGenericSpecializationTypeList();
GenericSpecializationTypeListContext* genericSpecializationTypeList();
ParameterListContext* parameterList();
OptionalTypeContext* optionalType();
OptionalLabelListContext* optionalLabelList();
......
......@@ -25,8 +25,8 @@ 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 visitGenericSpecializationTypeList(
TorqueParser::GenericSpecializationTypeListContext* context) = 0;
virtual antlrcpp::Any visitOptionalGenericTypeList(
TorqueParser::OptionalGenericTypeListContext* context) = 0;
......
......@@ -13,28 +13,6 @@ namespace torque {
namespace {
std::string GetType(TorqueParser::TypeContext* context) {
if (!context) return "void";
std::string result(context->CONSTEXPR() == nullptr ? ""
: CONSTEXPR_TYPE_PREFIX);
result += context->IDENTIFIER()->getSymbol()->getText();
return result;
}
std::string GetOptionalType(TorqueParser::OptionalTypeContext* context) {
if (!context) return "";
return GetType(context->type());
}
std::vector<std::string> GetTypeVector(
TorqueParser::TypeListContext* type_list) {
std::vector<std::string> result;
for (auto s : type_list->type()) {
result.push_back(GetType(s));
}
return result;
}
std::vector<std::string> GetIdentifierVector(
std::vector<antlr4::tree::TerminalNode*> source) {
std::vector<std::string> result;
......@@ -44,22 +22,6 @@ std::vector<std::string> GetIdentifierVector(
return result;
}
LabelAndTypesVector GetOptionalLabelAndTypeList(
TorqueParser::OptionalLabelListContext* context) {
LabelAndTypesVector labels;
if (context) {
for (auto label : context->labelParameter()) {
LabelAndTypes new_label;
new_label.name = label->IDENTIFIER()->getSymbol()->getText();
if (label->typeList() != nullptr) {
new_label.types = GetTypeVector(label->typeList());
}
labels.emplace_back(new_label);
}
}
return labels;
}
std::string StringLiteralUnquote(const std::string& s) {
assert('"' == s.front() || '\'' == s.front());
assert('"' == s.back() || '\'' == s.back());
......@@ -93,6 +55,54 @@ std::string StringLiteralUnquote(const std::string& s) {
} // namespace
LabelAndTypesVector AstGenerator::GetOptionalLabelAndTypeList(
TorqueParser::OptionalLabelListContext* context) {
LabelAndTypesVector labels;
if (context) {
for (auto* label : context->labelParameter()) {
LabelAndTypes new_label;
new_label.name = label->IDENTIFIER()->getSymbol()->getText();
if (label->typeList() != nullptr) {
for (auto* type : label->typeList()->type()) {
new_label.types.emplace_back(GetType(type));
}
}
labels.emplace_back(new_label);
}
}
return labels;
}
TypeExpression* AstGenerator::GetType(TorqueParser::TypeContext* context) {
if (context->BUILTIN()) {
ParameterList parameters = context->typeList()->accept(this);
TypeExpression* return_type = GetType(context->type());
return RegisterNode(
new FunctionTypeExpression(Pos(context), parameters, return_type));
} else {
bool is_constexpr = context->CONSTEXPR() != nullptr;
std::string name = context->IDENTIFIER()->getSymbol()->getText();
return RegisterNode(
new BasicTypeExpression(Pos(context), is_constexpr, std::move(name)));
}
}
TypeExpression* AstGenerator::GetOptionalType(
TorqueParser::OptionalTypeContext* context) {
if (!context->type())
return RegisterNode(new BasicTypeExpression(Pos(context), false, "void"));
return GetType(context->type());
}
std::vector<TypeExpression*> AstGenerator::GetTypeVector(
TorqueParser::TypeListContext* type_list) {
std::vector<TypeExpression*> result;
for (auto t : type_list->type()) {
result.push_back(GetType(t));
}
return result;
}
ParameterList AstGenerator::GetOptionalParameterList(
TorqueParser::ParameterListContext* context) {
if (context != nullptr) {
......@@ -256,8 +266,8 @@ antlrcpp::Any AstGenerator::visitExternalRuntime(
antlrcpp::Any AstGenerator::visitGenericSpecialization(
TorqueParser::GenericSpecializationContext* context) {
auto name = context->IDENTIFIER()->getSymbol()->getText();
auto specialization_parameters = GetIdentifierVector(
context->optionalGenericSpecializationTypeList()->IDENTIFIER());
auto specialization_parameters =
GetTypeVector(context->genericSpecializationTypeList()->typeList());
Statement* body = context->helperBody()->accept(this).as<Statement*>();
return implicit_cast<Declaration*>(RegisterNode(new SpecializationDeclaration{
Pos(context), name, specialization_parameters,
......@@ -330,14 +340,18 @@ antlrcpp::Any AstGenerator::visitHelperCall(
for (auto label : context->optionalOtherwise()->IDENTIFIER()) {
labels.push_back(label->getSymbol()->getText());
}
CallExpression* result = RegisterNode(new CallExpression{
Pos(context),
callee->getSymbol()->getText(),
is_operator,
GetIdentifierVector(
context->optionalGenericSpecializationTypeList()->IDENTIFIER()),
{},
labels});
std::vector<TypeExpression*> templateArguments;
if (context->genericSpecializationTypeList()) {
templateArguments =
GetTypeVector(context->genericSpecializationTypeList()->typeList());
}
CallExpression* result =
RegisterNode(new CallExpression{Pos(context),
callee->getSymbol()->getText(),
is_operator,
templateArguments,
{},
labels});
for (auto* arg : context->argumentList()->argument()) {
result->arguments.push_back(arg->accept(this).as<Expression*>());
}
......
......@@ -154,6 +154,13 @@ class AstGenerator : public TorqueBaseVisitor {
return node;
}
LabelAndTypesVector GetOptionalLabelAndTypeList(
TorqueParser::OptionalLabelListContext* context);
TypeExpression* GetType(TorqueParser::TypeContext* context);
TypeExpression* GetOptionalType(TorqueParser::OptionalTypeContext* context);
std::vector<TypeExpression*> GetTypeVector(
TorqueParser::TypeListContext* type_list);
ParameterList GetOptionalParameterList(
TorqueParser::ParameterListContext* context);
......
This diff is collapsed.
......@@ -20,13 +20,50 @@ bool Type::IsSubtypeOf(const Type* supertype) const {
return false;
}
std::string Type::GetGeneratedTNodeTypeName() const {
bool Type::IsAbstractName(const std::string& name) const {
if (!IsAbstractType()) return false;
return AbstractType::cast(this)->name() == name;
}
std::string AbstractType::GetGeneratedTNodeTypeName() const {
std::string result = GetGeneratedTypeName();
DCHECK_EQ(result.substr(0, 6), "TNode<");
result = result.substr(6, result.length() - 7);
return result;
}
std::string FunctionPointerType::ToString() const {
std::stringstream result;
result << "builtin (";
bool first = true;
for (const Type* t : parameter_types_) {
if (!first) {
result << ", ";
first = false;
}
result << t;
}
result << ") => " << return_type_;
return result.str();
}
std::string FunctionPointerType::MangledName() const {
std::stringstream result;
result << "FT";
bool first = true;
for (const Type* t : parameter_types_) {
if (!first) {
result << ", ";
first = false;
}
std::string arg_type_string = t->MangledName();
result << arg_type_string.size() << arg_type_string;
}
std::string return_type_string = return_type_->MangledName();
result << return_type_string.size() << return_type_string;
return result.str();
}
} // namespace torque
} // namespace internal
} // namespace v8
......@@ -8,6 +8,7 @@
#include <cassert>
#include <string>
#include "src/base/functional.h"
#include "src/base/logging.h"
#include "src/torque/ast.h"
#include "src/torque/types.h"
......@@ -24,7 +25,8 @@ class Declarable {
public:
virtual ~Declarable() {}
enum Kind {
kType,
kAbstractType,
kFunctionPointerType,
kVariable,
kParameter,
kMacro,
......@@ -36,9 +38,10 @@ class Declarable {
kLabel,
kConstant
};
explicit Declarable(Kind kind) : kind_(kind) {}
Kind kind() const { return kind_; }
bool IsType() const { return kind() == kType; }
bool IsAbstractType() const { return kind() == kAbstractType; }
bool IsFunctionPointerType() const { return kind() == kFunctionPointerType; }
bool IsType() const { return IsAbstractType() || IsFunctionPointerType(); }
bool IsMacro() const { return kind() == kMacro; }
bool IsBuiltin() const { return kind() == kBuiltin; }
bool IsRuntimeFunction() const { return kind() == kRuntimeFunction; }
......@@ -52,53 +55,130 @@ class Declarable {
bool IsValue() const { return IsVariable() || IsConstant() || IsParameter(); }
virtual const char* type_name() const { return "<<unknown>>"; }
protected:
explicit Declarable(Kind kind) : kind_(kind) {}
private:
Kind kind_;
};
#define DECLARE_DECLARABLE_BOILERPLATE(x, y) \
static x* cast(Declarable* declarable) { \
DCHECK(declarable->Is##x()); \
return static_cast<x*>(declarable); \
} \
static const x* cast(const Declarable* declarable) { \
DCHECK(declarable->Is##x()); \
return static_cast<const x*>(declarable); \
} \
const char* type_name() const override { return #y; }
#define DECLARE_DECLARABLE_BOILERPLATE(x, y) \
static x* cast(Declarable* declarable) { \
DCHECK(declarable->Is##x()); \
return static_cast<x*>(declarable); \
} \
static const x* cast(const Declarable* declarable) { \
DCHECK(declarable->Is##x()); \
return static_cast<const x*>(declarable); \
} \
const char* type_name() const override { return #y; } \
static x* DynamicCast(Declarable* declarable) { \
if (!declarable) return nullptr; \
if (!declarable->Is##x()) return nullptr; \
return static_cast<x*>(declarable); \
} \
static const x* DynamicCast(const Declarable* declarable) { \
if (!declarable) return nullptr; \
if (!declarable->Is##x()) return nullptr; \
return static_cast<const x*>(declarable); \
}
class Type : public Declarable {
public:
DECLARE_DECLARABLE_BOILERPLATE(Type, type);
Type(const Type* parent, const std::string& name,
const std::string& generated_type)
: Declarable(Declarable::kType),
parent_(parent),
bool IsSubtypeOf(const Type* supertype) const;
virtual std::string ToString() const = 0;
virtual std::string MangledName() const = 0;
bool IsVoid() const { return IsAbstractName(VOID_TYPE_STRING); }
bool IsNever() const { return IsAbstractName(NEVER_TYPE_STRING); }
bool IsBool() const { return IsAbstractName(BOOL_TYPE_STRING); }
bool IsConstexprBool() const {
return IsAbstractName(CONSTEXPR_BOOL_TYPE_STRING);
}
bool IsVoidOrNever() const { return IsVoid() || IsNever(); }
virtual const std::string& GetGeneratedTypeName() const = 0;
virtual std::string GetGeneratedTNodeTypeName() const = 0;
virtual bool IsConstexpr() const = 0;
protected:
Type(Declarable::Kind kind, const Type* parent)
: Declarable(kind), parent_(parent) {}
const Type* parent() const { return parent_; }
private:
bool IsAbstractName(const std::string& name) const;
const Type* const parent_;
};
class AbstractType : public Type {
public:
DECLARE_DECLARABLE_BOILERPLATE(AbstractType, abstract_type);
AbstractType(const Type* parent, const std::string& name,
const std::string& generated_type)
: Type(Declarable::kAbstractType, parent),
name_(name),
generated_type_(generated_type) {}
const Type* parent() const { return parent_; }
const std::string& name() const { return name_; }
const std::string& GetGeneratedTypeName() const { return generated_type_; }
std::string GetGeneratedTNodeTypeName() const;
bool IsSubtypeOf(const Type* supertype) const;
bool IsVoid() const { return name() == VOID_TYPE_STRING; }
bool IsNever() const { return name() == NEVER_TYPE_STRING; }
bool IsBool() const { return name() == BOOL_TYPE_STRING; }
bool IsConstexprBool() const { return name() == CONSTEXPR_BOOL_TYPE_STRING; }
bool IsVoidOrNever() const { return IsVoid() || IsNever(); }
bool IsConstexpr() const {
std::string ToString() const override { return name(); }
std::string MangledName() const override { return "AT" + name(); }
const std::string& GetGeneratedTypeName() const override {
return generated_type_;
}
std::string GetGeneratedTNodeTypeName() const override;
bool IsConstexpr() const override {
return name().substr(0, strlen(CONSTEXPR_TYPE_PREFIX)) ==
CONSTEXPR_TYPE_PREFIX;
}
private:
const Type* const parent_;
const std::string name_;
const std::string generated_type_;
};
// For now, function pointers are restricted to Code objects of Torque-defined
// builtins.
class FunctionPointerType : public Type {
public:
DECLARE_DECLARABLE_BOILERPLATE(FunctionPointerType, function_pointer_type);
FunctionPointerType(const Type* parent, TypeVector parameter_types,
const Type* return_type)
: Type(Declarable::kFunctionPointerType, parent),
parameter_types_(parameter_types),
return_type_(return_type) {}
std::string ToString() const override;
std::string MangledName() const override;
const std::string& GetGeneratedTypeName() const override {
return parent()->GetGeneratedTypeName();
}
std::string GetGeneratedTNodeTypeName() const override {
return parent()->GetGeneratedTNodeTypeName();
}
bool IsConstexpr() const override { return parent()->IsConstexpr(); }
const TypeVector& parameter_types() const { return parameter_types_; }
const Type* return_type() const { return return_type_; }
friend size_t hash_value(const FunctionPointerType& p) {
size_t result = base::hash_value(p.return_type_);
for (const Type* parameter : p.parameter_types_) {
result = base::hash_combine(result, parameter);
}
return result;
}
bool operator==(const FunctionPointerType& other) const {
return parameter_types_ == other.parameter_types_ &&
return_type_ == other.return_type_;
}
private:
const TypeVector parameter_types_;
const Type* const return_type_;
};
inline std::ostream& operator<<(std::ostream& os, const Type* t) {
os << t->name().c_str();
os << t->ToString();
return os;
}
......@@ -275,20 +355,24 @@ class MacroList : public Declarable {
class Builtin : public Callable {
public:
enum Kind { kStub = 0, kFixedArgsJavaScript, kVarArgsJavaScript };
enum Kind { kStub, kFixedArgsJavaScript, kVarArgsJavaScript };
DECLARE_DECLARABLE_BOILERPLATE(Builtin, builtin);
Kind kind() const { return kind_; }
bool IsStub() const { return kind_ == kStub; }
bool IsVarArgsJavaScript() const { return kind_ == kVarArgsJavaScript; }
bool IsFixedArgsJavaScript() const { return kind_ == kFixedArgsJavaScript; }
bool IsExternal() const { return external_; }
private:
friend class Declarations;
Builtin(const std::string& name, Builtin::Kind kind,
Builtin(const std::string& name, Builtin::Kind kind, bool external,
const Signature& signature)
: Callable(Declarable::kBuiltin, name, signature), kind_(kind) {}
: Callable(Declarable::kBuiltin, name, signature),
kind_(kind),
external_(external) {}
Kind kind_;
bool external_;
};
class RuntimeFunction : public Callable {
......
......@@ -58,7 +58,7 @@ void DeclarationVisitor::Visit(CallableNode* decl, const Signature& signature,
}
Builtin* DeclarationVisitor::BuiltinDeclarationCommon(
BuiltinDeclaration* decl, const Signature& signature) {
BuiltinDeclaration* decl, bool external, const Signature& signature) {
const bool javascript = decl->javascript_linkage;
const bool varargs = decl->signature->parameters.has_varargs;
Builtin::Kind kind = !javascript ? Builtin::kStub
......@@ -66,7 +66,8 @@ Builtin* DeclarationVisitor::BuiltinDeclarationCommon(
: Builtin::kFixedArgsJavaScript;
if (signature.types().size() == 0 ||
!(signature.types()[0]->name() == CONTEXT_TYPE_STRING)) {
!(signature.types()[0] ==
declarations()->LookupGlobalType(decl->pos, CONTEXT_TYPE_STRING))) {
std::stringstream stream;
stream << "first parameter to builtin " << decl->name
<< " is not a context but should be at "
......@@ -84,10 +85,11 @@ Builtin* DeclarationVisitor::BuiltinDeclarationCommon(
if (javascript) {
if (signature.types().size() < 2 ||
!(signature.types()[1]->name() == OBJECT_TYPE_STRING)) {
!(signature.types()[1] ==
declarations()->LookupGlobalType(decl->pos, OBJECT_TYPE_STRING))) {
std::stringstream stream;
stream << "second parameter to javascript builtin " << decl->name
<< " is not a receiver type but should be at "
<< " is " << signature.types()[1] << " but should be Object at "
<< PositionAsString(decl->pos);
ReportError(stream.str());
}
......@@ -96,7 +98,7 @@ Builtin* DeclarationVisitor::BuiltinDeclarationCommon(
std::string generated_name = GetGeneratedCallableName(
decl->name, declarations()->GetCurrentSpecializationTypeNamesVector());
return declarations()->DeclareBuiltin(decl->pos, generated_name, kind,
signature);
external, signature);
}
void DeclarationVisitor::Visit(ExternalRuntimeDeclaration* decl,
......@@ -107,7 +109,8 @@ void DeclarationVisitor::Visit(ExternalRuntimeDeclaration* decl,
}
if (signature.parameter_types.types.size() == 0 ||
!(signature.parameter_types.types[0]->name() == CONTEXT_TYPE_STRING)) {
!(signature.parameter_types.types[0] ==
declarations()->LookupGlobalType(CONTEXT_TYPE_STRING))) {
std::stringstream stream;
stream << "first parameter to runtime " << decl->name
<< " is not a context but should be at "
......@@ -161,7 +164,7 @@ void DeclarationVisitor::Visit(ExternalMacroDeclaration* decl,
void DeclarationVisitor::Visit(TorqueBuiltinDeclaration* decl,
const Signature& signature, Statement* body) {
Builtin* builtin = BuiltinDeclarationCommon(decl, signature);
Builtin* builtin = BuiltinDeclarationCommon(decl, false, signature);
CurrentCallableActivator activator(global_context_, builtin, decl);
DeclareSignature(decl->pos, builtin->signature());
if (builtin->signature().parameter_types.var_args) {
......@@ -280,8 +283,7 @@ void DeclarationVisitor::Visit(TryCatchStatement* stmt) {
for (auto p : block->parameters.names) {
shared_label->AddVariable(declarations()->DeclareVariable(
stmt->pos, p,
declarations()->LookupType(stmt->pos,
block->parameters.types[i])));
declarations()->GetType(stmt->pos, block->parameters.types[i])));
++i;
}
}
......@@ -307,10 +309,11 @@ void DeclarationVisitor::Visit(TryCatchStatement* stmt) {
void DeclarationVisitor::Visit(CallExpression* expr) {
if (expr->generic_arguments.size() != 0) {
Generic* generic = declarations()->LookupGeneric(expr->pos, expr->callee);
Generic* generic =
declarations()->LookupGeneric(expr->pos, expr->callee.name);
TypeVector specialization_types;
for (auto t : expr->generic_arguments) {
specialization_types.push_back(declarations()->LookupType(expr->pos, t));
specialization_types.push_back(declarations()->GetType(expr->pos, t));
}
CallableNode* callable = generic->declaration()->callable;
QueueGenericSpecialization({generic, specialization_types}, callable,
......
......@@ -74,22 +74,23 @@ class DeclarationVisitor : public FileVisitor {
std::string generates =
decl->generates ? *decl->generates : std::string("");
declarations()->DeclareType(decl->pos, decl->name, generates, extends_ptr);
declarations()->DeclareAbstractType(decl->pos, decl->name, generates,
extends_ptr);
if (decl->constexpr_generates) {
std::string constexpr_name =
std::string(CONSTEXPR_TYPE_PREFIX) + decl->name;
declarations()->DeclareType(decl->pos, constexpr_name,
*decl->constexpr_generates, &(decl->name));
declarations()->DeclareAbstractType(
decl->pos, constexpr_name, *decl->constexpr_generates, &(decl->name));
}
}
Builtin* BuiltinDeclarationCommon(BuiltinDeclaration* decl,
Builtin* BuiltinDeclarationCommon(BuiltinDeclaration* decl, bool external,
const Signature& signature);
void Visit(ExternalBuiltinDeclaration* decl, const Signature& signature,
Statement* body) {
BuiltinDeclarationCommon(decl, signature);
BuiltinDeclarationCommon(decl, true, signature);
}
void Visit(ExternalRuntimeDeclaration* decl, const Signature& sig,
......@@ -117,7 +118,7 @@ class DeclarationVisitor : public FileVisitor {
void Visit(VarDeclarationStatement* stmt) {
std::string variable_name = stmt->name;
const Type* type = declarations()->LookupType(stmt->pos, stmt->type);
const Type* type = declarations()->GetType(stmt->pos, stmt->type);
if (type->IsConstexpr()) {
std::stringstream stream;
stream << "cannot declare variable with constexpr type at "
......@@ -140,8 +141,8 @@ class DeclarationVisitor : public FileVisitor {
void Visit(ConstDeclaration* decl) {
declarations()->DeclareConstant(
decl->pos, decl->name,
declarations()->LookupType(decl->pos, decl->type), decl->literal);
decl->pos, decl->name, declarations()->GetType(decl->pos, decl->type),
decl->literal);
}
void Visit(LogicalOrExpression* expr) {
......
......@@ -59,6 +59,62 @@ const Type* Declarations::LookupType(SourcePosition pos,
return nullptr;
}
const Type* Declarations::LookupGlobalType(const std::string& name) {
return Type::cast(LookupGlobalScope(name));
}
const Type* Declarations::LookupGlobalType(SourcePosition pos,
const std::string& name) {
Declarable* raw = LookupGlobalScope(pos, name);
if (!raw->IsType()) {
std::stringstream s;
s << "declaration \"" << name << "\" is not a Type at "
<< PositionAsString(pos);
ReportError(s.str());
}
return Type::cast(raw);
}
const Type* Declarations::GetFunctionPointerType(SourcePosition pos,
TypeVector argument_types,
const Type* return_type) {
const Type* code_type = LookupGlobalType(pos, CODE_TYPE_STRING);
return function_pointer_types_.Add(
FunctionPointerType(code_type, argument_types, return_type));
}
const Type* Declarations::GetType(SourcePosition pos,
TypeExpression* type_expression) {
if (auto* basic = BasicTypeExpression::DynamicCast(type_expression)) {
std::string name =
(basic->is_constexpr ? CONSTEXPR_TYPE_PREFIX : "") + basic->name;
return LookupType(pos, name);
} else {
auto* function_type_exp = FunctionTypeExpression::cast(type_expression);
TypeVector argument_types;
for (TypeExpression* type_exp : function_type_exp->parameters.types) {
argument_types.push_back(GetType(pos, type_exp));
}
return GetFunctionPointerType(pos, argument_types,
GetType(pos, function_type_exp->return_type));
}
}
Builtin* Declarations::FindSomeInternalBuiltinWithType(
const FunctionPointerType* type) {
for (auto& declarable : declarables_) {
if (Builtin* builtin = Builtin::DynamicCast(declarable.get())) {
if (!builtin->IsExternal() && builtin->kind() == Builtin::kStub &&
builtin->signature().return_type == type->return_type() &&
builtin->signature().parameter_types.types ==
type->parameter_types()) {
return builtin;
}
}
}
return nullptr;
}
Value* Declarations::LookupValue(SourcePosition pos, const std::string& name) {
Declarable* d = Lookup(pos, name);
if (!d->IsValue()) {
......@@ -131,10 +187,9 @@ Generic* Declarations::LookupGeneric(const SourcePosition& pos,
return nullptr;
}
const Type* Declarations::DeclareType(SourcePosition pos,
const std::string& name,
const std::string& generated,
const std::string* parent) {
const AbstractType* Declarations::DeclareAbstractType(
SourcePosition pos, const std::string& name, const std::string& generated,
const std::string* parent) {
CheckAlreadyDeclared(pos, name, "type");
const Type* parent_type = nullptr;
if (parent != nullptr) {
......@@ -154,7 +209,7 @@ const Type* Declarations::DeclareType(SourcePosition pos,
}
parent_type = Type::cast(maybe_parent_type);
}
Type* result = new Type(parent_type, name, generated);
AbstractType* result = new AbstractType(parent_type, name, generated);
Declare(name, std::unique_ptr<Declarable>(result));
return result;
}
......@@ -205,10 +260,10 @@ Macro* Declarations::DeclareMacro(SourcePosition pos, const std::string& name,
Builtin* Declarations::DeclareBuiltin(SourcePosition pos,
const std::string& name,
Builtin::Kind kind,
Builtin::Kind kind, bool external,
const Signature& signature) {
CheckAlreadyDeclared(pos, name, "builtin");
Builtin* result = new Builtin(name, kind, signature);
Builtin* result = new Builtin(name, kind, external, signature);
Declare(name, std::unique_ptr<Declarable>(result));
return result;
}
......
......@@ -9,6 +9,7 @@
#include "src/torque/declarable.h"
#include "src/torque/scope.h"
#include "src/torque/utils.h"
namespace v8 {
namespace internal {
......@@ -33,7 +34,31 @@ class Declarations {
return d;
}
Declarable* LookupGlobalScope(const std::string& name) {
return chain_.LookupGlobalScope(name);
}
Declarable* LookupGlobalScope(SourcePosition pos, const std::string& name) {
Declarable* d = chain_.LookupGlobalScope(name);
if (d == nullptr) {
std::stringstream s;
s << "cannot find \"" << name << "\" in global scope at "
<< PositionAsString(pos);
ReportError(s.str());
}
return d;
}
const Type* LookupType(SourcePosition pos, const std::string& name);
const Type* LookupGlobalType(const std::string& name);
const Type* LookupGlobalType(SourcePosition pos, const std::string& name);
const Type* GetType(SourcePosition pos, TypeExpression* type_expression);
const Type* GetFunctionPointerType(SourcePosition pos,
TypeVector argument_types,
const Type* return_type);
Builtin* FindSomeInternalBuiltinWithType(const FunctionPointerType* type);
Value* LookupValue(SourcePosition pos, const std::string& name);
......@@ -46,9 +71,10 @@ class Declarations {
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);
const AbstractType* DeclareAbstractType(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);
......@@ -59,7 +85,8 @@ class Declarations {
const Signature& signature);
Builtin* DeclareBuiltin(SourcePosition pos, const std::string& name,
const Builtin::Kind kind, const Signature& signature);
Builtin::Kind kind, bool external,
const Signature& signature);
RuntimeFunction* DeclareRuntimeFunction(SourcePosition pos,
const std::string& name,
......@@ -104,10 +131,15 @@ class Declarations {
Scope* GetNodeScope(const AstNode* node);
Scope* GetGenericScope(Generic* generic, const TypeVector& types);
template <class T>
T* RegisterDeclarable(std::unique_ptr<T> d) {
T* ptr = d.get();
declarables_.push_back(std::move(d));
return ptr;
}
void Declare(const std::string& name, std::unique_ptr<Declarable> d) {
Declarable* ptr = d.get();
declarables_.emplace_back(std::move(d));
chain_.Declare(name, ptr);
chain_.Declare(name, RegisterDeclarable(std::move(d)));
}
int GetNextUniqueDeclarationNumber() { return unique_declaration_number_++; }
......@@ -121,6 +153,7 @@ class Declarations {
const SpecializationKey* current_generic_specialization_;
Statement* next_body_;
std::vector<std::unique_ptr<Declarable>> declarables_;
Deduplicator<FunctionPointerType> function_pointer_types_;
std::map<std::pair<const AstNode*, TypeVector>, Scope*> scopes_;
std::map<Generic*, ScopeChain::Snapshot> generic_declaration_scopes_;
};
......
......@@ -18,12 +18,11 @@ Signature FileVisitor::MakeSignature(CallableNode* decl,
LabelDeclaration def = {label.name, GetTypeVector(decl->pos, label.types)};
definition_vector.push_back(def);
}
Signature result{
signature->parameters.names,
{GetTypeVector(decl->pos, signature->parameters.types),
signature->parameters.has_varargs},
declarations()->LookupType(decl->pos, signature->return_type),
definition_vector};
Signature result{signature->parameters.names,
{GetTypeVector(decl->pos, signature->parameters.types),
signature->parameters.has_varargs},
declarations()->GetType(decl->pos, signature->return_type),
definition_vector};
return result;
}
......@@ -31,8 +30,8 @@ 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();
std::string type_string = type->MangledName();
result += std::to_string(type_string.size()) + type_string;
}
return result;
}
......@@ -69,7 +68,8 @@ Callable* FileVisitor::LookupCall(SourcePosition pos, const std::string& name,
}
} else {
std::stringstream stream;
stream << "can't call " << name << " because it's not callable"
stream << "can't call " << declarable->type_name() << " " << name
<< " because it's not callable"
<< ": call parameters were (" << parameter_types << ") at "
<< PositionAsString(pos);
ReportError(stream.str());
......
......@@ -27,10 +27,10 @@ class FileVisitor {
module_(global_context.GetDefaultModule()) {}
TypeVector GetTypeVector(SourcePosition pos,
const std::vector<std::string>& v) {
const std::vector<TypeExpression*>& v) {
TypeVector result;
for (const std::string& s : v) {
result.push_back(declarations()->LookupType(pos, s));
for (TypeExpression* t : v) {
result.push_back(declarations()->GetType(pos, t));
}
return result;
}
......
......@@ -495,19 +495,37 @@ VisitResult ImplementationVisitor::Visit(StringLiteralExpression* expr) {
return VisitResult{GetTypeOracle().GetStringType(), temp};
}
VisitResult ImplementationVisitor::GetBuiltinCode(SourcePosition pos,
Builtin* builtin) {
if (builtin->IsExternal() || builtin->kind() != Builtin::kStub) {
std::stringstream s;
s << "creating function pointers is only allowed for internal builtins "
"with stub linkage at "
<< PositionAsString(pos);
ReportError(s.str());
}
const Type* type = declarations()->GetFunctionPointerType(
pos, builtin->signature().parameter_types.types,
builtin->signature().return_type);
std::string code =
"HeapConstant(Builtins::CallableFor(isolate(), Builtins::k" +
builtin->name() + ").code())";
return VisitResult(type, code);
}
VisitResult ImplementationVisitor::Visit(CastExpression* expr) {
Arguments args;
args.parameters = {Visit(expr->value)};
args.labels = LabelsFromIdentifiers(expr->pos, {expr->otherwise});
return GenerateOperation(expr->pos, "cast<>", args,
declarations()->LookupType(expr->pos, expr->type));
declarations()->GetType(expr->pos, expr->type));
}
VisitResult ImplementationVisitor::Visit(ConvertExpression* expr) {
Arguments args;
args.parameters = {Visit(expr->value)};
return GenerateOperation(expr->pos, "convert<>", args,
declarations()->LookupType(expr->pos, expr->type));
declarations()->GetType(expr->pos, expr->type));
}
const Type* ImplementationVisitor::Visit(GotoStatement* stmt) {
......@@ -1281,6 +1299,65 @@ void ImplementationVisitor::GenerateParameterList(SourcePosition pos,
}
}
VisitResult ImplementationVisitor::GeneratePointerCall(
SourcePosition pos, Expression* callee, const Arguments& arguments,
bool is_tailcall) {
TypeVector parameter_types(arguments.parameters.GetTypeVector());
VisitResult callee_result = Visit(callee);
if (!callee_result.type()->IsFunctionPointerType()) {
std::stringstream stream;
stream << "Expected a function pointer type but found "
<< callee_result.type() << " at " << PositionAsString(pos);
ReportError(stream.str());
}
const FunctionPointerType* type =
FunctionPointerType::cast(callee_result.type());
std::vector<std::string> variables;
for (size_t current = 0; current < arguments.parameters.size(); ++current) {
const Type* to_type = type->parameter_types()[current];
VisitResult result =
GenerateImplicitConvert(pos, to_type, arguments.parameters[current]);
variables.push_back(result.variable());
}
std::string result_variable_name;
bool no_result = type->return_type()->IsVoidOrNever() || is_tailcall;
if (no_result) {
GenerateIndent();
} else {
result_variable_name = GenerateNewTempVariable(type->return_type());
source_out() << "UncheckedCast<";
source_out() << type->return_type()->GetGeneratedTNodeTypeName();
source_out() << ">(";
}
Builtin* example_builtin =
declarations()->FindSomeInternalBuiltinWithType(type);
if (is_tailcall) {
source_out() << "TailCallStub(";
} else {
source_out() << "CallStub(";
}
source_out() << "Builtins::CallableFor(isolate(), Builtins::k"
<< example_builtin->name() << ").descriptor(), "
<< callee_result.variable() << ", ";
size_t total_parameters = 0;
for (size_t i = 0; i < arguments.parameters.size(); ++i) {
if (total_parameters++ != 0) {
source_out() << ", ";
}
source_out() << variables[i];
}
if (!no_result) {
source_out() << ")";
}
source_out() << ");" << std::endl;
return VisitResult(type->return_type(), result_variable_name);
}
VisitResult ImplementationVisitor::GenerateCall(
SourcePosition pos, const std::string& callable_name,
const Arguments& arguments, bool is_tailcall) {
......@@ -1415,9 +1492,11 @@ void ImplementationVisitor::Visit(SpecializationDeclaration* decl) {
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);
std::string name = expr->callee.name;
bool has_template_arguments = expr->generic_arguments.size() != 0;
if (has_template_arguments) {
Generic* generic =
declarations()->LookupGeneric(expr->pos, expr->callee.name);
TypeVector specialization_types =
GetTypeVector(expr->pos, expr->generic_arguments);
name = GetGeneratedCallableName(name, specialization_types);
......@@ -1437,7 +1516,14 @@ VisitResult ImplementationVisitor::Visit(CallExpression* expr,
}
return GenerateOperation(expr->pos, name, arguments);
}
VisitResult result = GenerateCall(expr->pos, name, arguments, is_tailcall);
VisitResult result;
if (!has_template_arguments &&
declarations()->Lookup(expr->pos, expr->callee.name)->IsValue()) {
result =
GeneratePointerCall(expr->pos, &expr->callee, arguments, is_tailcall);
} else {
result = GenerateCall(expr->pos, name, arguments, is_tailcall);
}
if (!result.type()->IsVoidOrNever()) {
GenerateIndent();
source_out() << "USE(" << result.variable() << ");" << std::endl;
......
......@@ -76,7 +76,13 @@ class ImplementationVisitor : public FileVisitor {
return GenerateOperation(expr->pos, "[]", arguments);
}
VisitResult GetBuiltinCode(SourcePosition pos, Builtin* builtin);
VisitResult Visit(IdentifierExpression* expr) {
if (Builtin* builtin =
Builtin::DynamicCast(declarations()->Lookup(expr->name))) {
return GetBuiltinCode(expr->pos, builtin);
}
return GenerateFetchFromLocation(expr, GetLocationReference(expr));
}
VisitResult Visit(FieldAccessExpression* expr) {
......@@ -201,6 +207,8 @@ class ImplementationVisitor : public FileVisitor {
VisitResult GenerateCall(SourcePosition pos, const std::string& callable_name,
const Arguments& parameters, bool tail_call);
VisitResult GeneratePointerCall(SourcePosition pos, Expression* callee,
const Arguments& parameters, bool tail_call);
bool GenerateLabeledStatementBlocks(
const std::vector<Statement*>& blocks,
......
......@@ -112,6 +112,11 @@ class ScopeChain {
return e->Lookup(name);
}
Declarable* LookupGlobalScope(const std::string& name) {
auto& e = current_scopes_.front();
return e->Lookup(name);
}
void Print() {
for (auto s : current_scopes_) {
s->Print();
......
......@@ -77,9 +77,7 @@ class TypeOracle {
private:
const Type* GetBuiltinType(const std::string& name) {
Declarable* declarable = declarations_->Lookup(name);
DCHECK(declarable != nullptr);
return Type::cast(declarable);
return declarations_->LookupGlobalType(name);
}
Declarations* declarations_;
......
......@@ -23,6 +23,7 @@ static const char* const ARGUMENTS_TYPE_STRING = "Arguments";
static const char* const CONTEXT_TYPE_STRING = "Context";
static const char* const OBJECT_TYPE_STRING = "Object";
static const char* const STRING_TYPE_STRING = "String";
static const char* const CODE_TYPE_STRING = "Code";
static const char* const INTPTR_TYPE_STRING = "intptr";
static const char* const CONST_INT31_TYPE_STRING = "constexpr int31";
static const char* const CONST_INT32_TYPE_STRING = "constexpr int32";
......
......@@ -6,8 +6,11 @@
#define V8_TORQUE_UTILS_H_
#include <string>
#include <unordered_set>
#include <vector>
#include "src/base/functional.h"
namespace v8 {
namespace internal {
namespace torque {
......@@ -22,6 +25,15 @@ std::string DashifyString(const std::string& underscore_string);
void ReplaceFileContentsIfDifferent(const std::string& file_path,
const std::string& contents);
template <class T>
class Deduplicator {
public:
const T* Add(T x) { return &*(storage_.insert(std::move(x)).first); }
private:
std::unordered_set<T, base::hash<T>> storage_;
};
} // namespace torque
} // namespace internal
} // namespace v8
......
......@@ -124,6 +124,20 @@ TEST(TestMacroSpecialization) {
FunctionTester ft(asm_tester.GenerateCode(), 0);
}
TEST(TestFunctionPointers) {
Isolate* isolate(CcTest::InitIsolateOnce());
const int kNumParams = 0;
CodeAssemblerTester asm_tester(isolate, kNumParams);
TestBuiltinsFromDSLAssembler m(asm_tester.state());
{
TNode<Context> context =
m.UncheckedCast<Context>(m.Parameter(kNumParams + 2));
m.Return(m.TestFunctionPointers(context));
}
FunctionTester ft(asm_tester.GenerateCode(), 0);
ft.CheckCall(ft.true_value());
}
} // namespace compiler
} // namespace internal
} // namespace v8
......@@ -158,4 +158,19 @@ module test {
unreachable;
}
}
builtin TestHelperPlus1(context : Context, x : Smi) : Smi {
return x + 1;
}
builtin TestHelperPlus2(context : Context, x : Smi) : Smi {
return x + 2;
}
macro TestFunctionPointers(context : Context) : Boolean {
let fptr : builtin(Context, Smi) => Smi = TestHelperPlus1;
assert(fptr(context, 42) == 43);
fptr = TestHelperPlus2;
assert(fptr(context, 42) == 44);
return True;
}
}
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