Commit b07d55f5 authored by Simon Zünd's avatar Simon Zünd Committed by Commit Bot

[torque] Allow function pointers to generic builtins.

This CL adds grammar support for function pointers to generic builtins.
It also instantiates generic specializations when they are only used
in an assignment to a function pointer.

Example:

builtin GenericBuiltinTest<T: type>(c: Context, param: T): Object {
  return Null;
}

let fnptr: builtin(Context, Smi) => Object = GenericBuiltinTest<Smi>;

Change-Id: Ib7e5f47ffc05f14eb5d0b789936587263dfb961d
Reviewed-on: https://chromium-review.googlesource.com/1068731
Commit-Queue: Simon Zünd <szuend@google.com>
Reviewed-by: 's avatarTobias Tebbi <tebbi@chromium.org>
Cr-Commit-Position: refs/heads/master@{#53284}
parent ccee44e1
......@@ -188,7 +188,7 @@ unaryExpression
| op=(PLUS | MINUS | BIT_NOT | NOT) unaryExpression;
locationExpression
: IDENTIFIER
: IDENTIFIER genericSpecializationTypeList?
| locationExpression '.' IDENTIFIER
| locationExpression '[' expression ']';
......@@ -229,7 +229,7 @@ helperCall: (MIN | MAX | IDENTIFIER) genericSpecializationTypeList? argumentList
labelReference: IDENTIFIER;
variableDeclaration: LET IDENTIFIER ':' type;
variableDeclarationWithInitialization: variableDeclaration ('=' expression)?;
variableDeclarationWithInitialization: variableDeclaration (ASSIGNMENT expression)?;
helperCallStatement: (TAIL)? helperCall;
expressionStatement: assignment;
ifStatement: IF CONSTEXPR? '(' expression ')' statementBlock ('else' statementBlock)?;
......
This source diff could not be displayed because it is too large. You can view the blob instead.
......@@ -655,6 +655,7 @@ class TorqueParser : public antlr4::Parser {
size_t invokingState);
size_t getRuleIndex() const override;
antlr4::tree::TerminalNode* IDENTIFIER();
GenericSpecializationTypeListContext* genericSpecializationTypeList();
LocationExpressionContext* locationExpression();
ExpressionContext* expression();
......@@ -913,6 +914,7 @@ class TorqueParser : public antlr4::Parser {
antlr4::ParserRuleContext* parent, size_t invokingState);
size_t getRuleIndex() const override;
VariableDeclarationContext* variableDeclaration();
antlr4::tree::TerminalNode* ASSIGNMENT();
ExpressionContext* expression();
void enterRule(antlr4::tree::ParseTreeListener* listener) override;
......
......@@ -583,8 +583,14 @@ antlrcpp::Any AstGenerator::visitLocationExpression(
Pos(context), location,
context->IDENTIFIER()->getSymbol()->getText()}));
}
std::vector<TypeExpression*> templateArguments;
if (context->genericSpecializationTypeList()) {
templateArguments =
GetTypeVector(context->genericSpecializationTypeList()->typeList());
}
return implicit_cast<Expression*>(RegisterNode(new IdentifierExpression{
Pos(context), context->IDENTIFIER()->getSymbol()->getText()}));
Pos(context), context->IDENTIFIER()->getSymbol()->getText(),
std::move(templateArguments)}));
}
antlrcpp::Any AstGenerator::visitUnaryExpression(
......
......@@ -235,9 +235,13 @@ class Ast {
struct IdentifierExpression : LocationExpression {
DEFINE_AST_NODE_LEAF_BOILERPLATE(IdentifierExpression)
IdentifierExpression(SourcePosition p, std::string n)
: LocationExpression(kKind, p), name(std::move(n)) {}
IdentifierExpression(SourcePosition p, std::string n,
std::vector<TypeExpression*> args)
: LocationExpression(kKind, p),
name(std::move(n)),
generic_arguments(std::move(args)) {}
std::string name;
std::vector<TypeExpression*> generic_arguments;
};
struct CallExpression : Expression {
......@@ -246,14 +250,12 @@ struct CallExpression : Expression {
std::vector<TypeExpression*> ga, std::vector<Expression*> a,
std::vector<std::string> l)
: Expression(kKind, p),
callee(p, std::move(c)),
callee(p, std::move(c), std::move(ga)),
is_operator(o),
generic_arguments(ga),
arguments(std::move(a)),
labels(l) {}
IdentifierExpression callee;
bool is_operator;
std::vector<TypeExpression*> generic_arguments;
std::vector<Expression*> arguments;
std::vector<std::string> labels;
};
......
......@@ -302,9 +302,9 @@ void DeclarationVisitor::Visit(TryCatchStatement* stmt) {
}
}
void DeclarationVisitor::Visit(CallExpression* expr) {
void DeclarationVisitor::Visit(IdentifierExpression* expr) {
if (expr->generic_arguments.size() != 0) {
Generic* generic = declarations()->LookupGeneric(expr->callee.name);
Generic* generic = declarations()->LookupGeneric(expr->name);
TypeVector specialization_types;
for (auto t : expr->generic_arguments) {
specialization_types.push_back(declarations()->GetType(t));
......@@ -314,7 +314,10 @@ void DeclarationVisitor::Visit(CallExpression* expr) {
callable->signature.get(),
generic->declaration()->body);
}
}
void DeclarationVisitor::Visit(CallExpression* expr) {
Visit(&expr->callee);
for (Expression* arg : expr->arguments) Visit(arg);
}
......
......@@ -50,7 +50,7 @@ class DeclarationVisitor : public FileVisitor {
Visit(implicit_cast<ModuleDeclaration*>(decl));
}
void Visit(IdentifierExpression* expr) {}
void Visit(IdentifierExpression* expr);
void Visit(NumberLiteralExpression* expr) {}
void Visit(StringLiteralExpression* expr) {}
void Visit(CallExpression* expr);
......
......@@ -500,6 +500,25 @@ VisitResult ImplementationVisitor::GetBuiltinCode(Builtin* builtin) {
return VisitResult(type, code);
}
VisitResult ImplementationVisitor::Visit(IdentifierExpression* expr) {
std::string name = expr->name;
if (expr->generic_arguments.size() != 0) {
Generic* generic = declarations()->LookupGeneric(expr->name);
TypeVector specialization_types = GetTypeVector(expr->generic_arguments);
name = GetGeneratedCallableName(name, specialization_types);
CallableNode* callable = generic->declaration()->callable;
QueueGenericSpecialization({generic, specialization_types}, callable,
callable->signature.get(),
generic->declaration()->body);
}
if (Builtin* builtin = Builtin::DynamicCast(declarations()->Lookup(name))) {
return GetBuiltinCode(builtin);
}
return GenerateFetchFromLocation(expr, GetLocationReference(expr));
}
VisitResult ImplementationVisitor::Visit(CastExpression* expr) {
Arguments args;
args.parameters = {Visit(expr->value)};
......@@ -1447,10 +1466,11 @@ VisitResult ImplementationVisitor::Visit(CallExpression* expr,
bool is_tailcall) {
Arguments arguments;
std::string name = expr->callee.name;
bool has_template_arguments = expr->generic_arguments.size() != 0;
bool has_template_arguments = expr->callee.generic_arguments.size() != 0;
if (has_template_arguments) {
Generic* generic = declarations()->LookupGeneric(expr->callee.name);
TypeVector specialization_types = GetTypeVector(expr->generic_arguments);
TypeVector specialization_types =
GetTypeVector(expr->callee.generic_arguments);
name = GetGeneratedCallableName(name, specialization_types);
CallableNode* callable = generic->declaration()->callable;
QueueGenericSpecialization({generic, specialization_types}, callable,
......
......@@ -75,13 +75,7 @@ class ImplementationVisitor : public FileVisitor {
VisitResult GetBuiltinCode(Builtin* builtin);
VisitResult Visit(IdentifierExpression* expr) {
if (Builtin* builtin =
Builtin::DynamicCast(declarations()->Lookup(expr->name))) {
return GetBuiltinCode(builtin);
}
return GenerateFetchFromLocation(expr, GetLocationReference(expr));
}
VisitResult Visit(IdentifierExpression* expr);
VisitResult Visit(FieldAccessExpression* expr) {
return GenerateFetchFromLocation(expr, GetLocationReference(expr));
}
......
......@@ -41,6 +41,7 @@ TEST(TestConstexpr1) {
m.Return(m.UndefinedConstant());
}
FunctionTester ft(asm_tester.GenerateCode(), 0);
ft.Call();
}
TEST(TestConstexprIf) {
......@@ -52,6 +53,7 @@ TEST(TestConstexprIf) {
m.Return(m.UndefinedConstant());
}
FunctionTester ft(asm_tester.GenerateCode(), 0);
ft.Call();
}
TEST(TestConstexprReturn) {
......@@ -63,6 +65,7 @@ TEST(TestConstexprReturn) {
m.Return(m.UndefinedConstant());
}
FunctionTester ft(asm_tester.GenerateCode(), 0);
ft.Call();
}
TEST(TestGotoLabel) {
......@@ -111,6 +114,7 @@ TEST(TestBuiltinSpecialization) {
m.Return(m.UndefinedConstant());
}
FunctionTester ft(asm_tester.GenerateCode(), 0);
ft.Call();
}
TEST(TestMacroSpecialization) {
......@@ -122,6 +126,7 @@ TEST(TestMacroSpecialization) {
m.Return(m.UndefinedConstant());
}
FunctionTester ft(asm_tester.GenerateCode(), 0);
ft.Call();
}
TEST(TestFunctionPointers) {
......@@ -138,6 +143,19 @@ TEST(TestFunctionPointers) {
ft.CheckCall(ft.true_value());
}
TEST(TestFunctionPointerToGeneric) {
Isolate* isolate(CcTest::InitIsolateOnce());
CodeAssemblerTester asm_tester(isolate, 0);
TestBuiltinsFromDSLAssembler m(asm_tester.state());
{
Node* temp = m.SmiConstant(0);
m.TestFunctionPointerToGeneric(m.UncheckedCast<Context>(temp));
m.Return(m.UndefinedConstant());
}
FunctionTester ft(asm_tester.GenerateCode(), 0);
ft.Call();
}
} // namespace compiler
} // namespace internal
} // namespace v8
......@@ -179,4 +179,14 @@ module test {
let var2 : Number = 42 == 0 ? 1 : 0;
return True;
}
macro TestFunctionPointerToGeneric(c: Context) {
let fptr1: builtin(Context, Smi) => Object = GenericBuiltinTest<Smi>;
let fptr2: builtin(Context, Object) => Object = GenericBuiltinTest<Object>;
assert(fptr1(c, 0) == Null);
assert(fptr1(c, 1) == Null);
assert(fptr2(c, Undefined) == Undefined);
assert(fptr2(c, Undefined) == Undefined);
}
}
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