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

[torque] Add module-wide const bindings

This CL adds constants that can be defined in the module scope:

const kConstexprConst: constexpr int31 = 5;
const kIntptrConst: intptr = 4;
const kSmiConst: Smi = 3;

They are implemented by generating "mini-macros" that return the
expression on the right-hand side of the assignment.

Bug: v8:7793
Change-Id: I0a476cb3111707fad56bf15e9547b377c7adab37
Reviewed-on: https://chromium-review.googlesource.com/1114745
Commit-Queue: Simon Zünd <szuend@google.com>
Reviewed-by: 's avatarDaniel Clifford <danno@chromium.org>
Reviewed-by: 's avatarTobias Tebbi <tebbi@chromium.org>
Cr-Commit-Position: refs/heads/master@{#54430}
parent 3def7348
......@@ -278,6 +278,7 @@ builtinDeclaration : JAVASCRIPT? BUILTIN IDENTIFIER optionalGenericTypeList para
genericSpecialization: IDENTIFIER genericSpecializationTypeList parameterList optionalType optionalLabelList helperBody;
macroDeclaration : ('operator' STRING_LITERAL)? MACRO IDENTIFIER optionalGenericTypeList parameterList optionalType optionalLabelList (helperBody | ';');
externConstDeclaration : 'const' IDENTIFIER ':' type generatesDeclaration ';';
constDeclaration: 'const' IDENTIFIER ':' type ASSIGNMENT expression ';';
declaration
: typeDeclaration
......@@ -288,7 +289,8 @@ declaration
| externalMacro
| externalBuiltin
| externalRuntime
| externConstDeclaration;
| externConstDeclaration
| constDeclaration;
moduleDeclaration : MODULE IDENTIFIER '{' declaration* '}';
......
......@@ -323,6 +323,11 @@ class TorqueBaseListener : public TorqueListener {
void exitExternConstDeclaration(
TorqueParser::ExternConstDeclarationContext* /*ctx*/) override {}
void enterConstDeclaration(
TorqueParser::ConstDeclarationContext* /*ctx*/) override {}
void exitConstDeclaration(
TorqueParser::ConstDeclarationContext* /*ctx*/) override {}
void enterDeclaration(TorqueParser::DeclarationContext* /*ctx*/) override {}
void exitDeclaration(TorqueParser::DeclarationContext* /*ctx*/) override {}
......
......@@ -341,6 +341,11 @@ class TorqueBaseVisitor : public TorqueVisitor {
return visitChildren(ctx);
}
antlrcpp::Any visitConstDeclaration(
TorqueParser::ConstDeclarationContext* ctx) override {
return visitChildren(ctx);
}
antlrcpp::Any visitDeclaration(
TorqueParser::DeclarationContext* ctx) override {
return visitChildren(ctx);
......
......@@ -306,6 +306,11 @@ class TorqueListener : public antlr4::tree::ParseTreeListener {
virtual void exitExternConstDeclaration(
TorqueParser::ExternConstDeclarationContext* ctx) = 0;
virtual void enterConstDeclaration(
TorqueParser::ConstDeclarationContext* ctx) = 0;
virtual void exitConstDeclaration(
TorqueParser::ConstDeclarationContext* ctx) = 0;
virtual void enterDeclaration(TorqueParser::DeclarationContext* ctx) = 0;
virtual void exitDeclaration(TorqueParser::DeclarationContext* ctx) = 0;
......
This source diff could not be displayed because it is too large. You can view the blob instead.
......@@ -163,9 +163,10 @@ class TorqueParser : public antlr4::Parser {
RuleGenericSpecialization = 64,
RuleMacroDeclaration = 65,
RuleExternConstDeclaration = 66,
RuleDeclaration = 67,
RuleModuleDeclaration = 68,
RuleFile = 69
RuleConstDeclaration = 67,
RuleDeclaration = 68,
RuleModuleDeclaration = 69,
RuleFile = 70
};
explicit TorqueParser(antlr4::TokenStream* input);
......@@ -246,6 +247,7 @@ class TorqueParser : public antlr4::Parser {
class GenericSpecializationContext;
class MacroDeclarationContext;
class ExternConstDeclarationContext;
class ConstDeclarationContext;
class DeclarationContext;
class ModuleDeclarationContext;
class FileContext;
......@@ -1414,6 +1416,24 @@ class TorqueParser : public antlr4::Parser {
ExternConstDeclarationContext* externConstDeclaration();
class ConstDeclarationContext : public antlr4::ParserRuleContext {
public:
ConstDeclarationContext(antlr4::ParserRuleContext* parent,
size_t invokingState);
size_t getRuleIndex() const override;
antlr4::tree::TerminalNode* IDENTIFIER();
TypeContext* type();
antlr4::tree::TerminalNode* ASSIGNMENT();
ExpressionContext* expression();
void enterRule(antlr4::tree::ParseTreeListener* listener) override;
void exitRule(antlr4::tree::ParseTreeListener* listener) override;
antlrcpp::Any accept(antlr4::tree::ParseTreeVisitor* visitor) override;
};
ConstDeclarationContext* constDeclaration();
class DeclarationContext : public antlr4::ParserRuleContext {
public:
DeclarationContext(antlr4::ParserRuleContext* parent, size_t invokingState);
......@@ -1427,6 +1447,7 @@ class TorqueParser : public antlr4::Parser {
ExternalBuiltinContext* externalBuiltin();
ExternalRuntimeContext* externalRuntime();
ExternConstDeclarationContext* externConstDeclaration();
ConstDeclarationContext* constDeclaration();
void enterRule(antlr4::tree::ParseTreeListener* listener) override;
void exitRule(antlr4::tree::ParseTreeListener* listener) override;
......
......@@ -219,6 +219,9 @@ class TorqueVisitor : public antlr4::tree::AbstractParseTreeVisitor {
virtual antlrcpp::Any visitExternConstDeclaration(
TorqueParser::ExternConstDeclarationContext* context) = 0;
virtual antlrcpp::Any visitConstDeclaration(
TorqueParser::ConstDeclarationContext* context) = 0;
virtual antlrcpp::Any visitDeclaration(
TorqueParser::DeclarationContext* context) = 0;
......
......@@ -278,6 +278,16 @@ antlrcpp::Any AstGenerator::visitExternalRuntime(
RegisterNode(new StandardDeclaration{Pos(context), runtime, nullptr}));
}
antlrcpp::Any AstGenerator::visitConstDeclaration(
TorqueParser::ConstDeclarationContext* context) {
auto name = context->IDENTIFIER()->getSymbol()->getText();
auto type = GetType(context->type());
Expression* expression =
context->expression()->accept(this).as<Expression*>();
return implicit_cast<Declaration*>(
RegisterNode(new ConstDeclaration{Pos(context), name, type, expression}));
}
antlrcpp::Any AstGenerator::visitGenericSpecialization(
TorqueParser::GenericSpecializationContext* context) {
auto name = context->IDENTIFIER()->getSymbol()->getText();
......
......@@ -41,6 +41,9 @@ class AstGenerator : public TorqueBaseVisitor {
antlrcpp::Any visitExternalRuntime(
TorqueParser::ExternalRuntimeContext* context) override;
antlrcpp::Any visitConstDeclaration(
TorqueParser::ConstDeclarationContext* context) override;
antlrcpp::Any visitGenericSpecialization(
TorqueParser::GenericSpecializationContext* context) override;
......
......@@ -70,7 +70,8 @@ DECLARE_CONTEXTUAL_VARIABLE(CurrentSourcePosition, SourcePosition)
V(SpecializationDeclaration) \
V(ExternConstDeclaration) \
V(DefaultModuleDeclaration) \
V(ExplicitModuleDeclaration)
V(ExplicitModuleDeclaration) \
V(ConstDeclaration)
#define AST_CALLABLE_NODE_KIND_LIST(V) \
V(TorqueMacroDeclaration) \
......@@ -623,6 +624,16 @@ struct ExternalRuntimeDeclaration : CallableNode {
: CallableNode(kKind, p, n, pl, r, {}) {}
};
struct ConstDeclaration : Declaration {
DEFINE_AST_NODE_LEAF_BOILERPLATE(ConstDeclaration)
ConstDeclaration(SourcePosition p, std::string n, TypeExpression* r,
Expression* e)
: Declaration(kKind, p), name(std::move(n)), type(r), expression(e) {}
std::string name;
TypeExpression* type;
Expression* expression;
};
struct StandardDeclaration : Declaration {
DEFINE_AST_NODE_LEAF_BOILERPLATE(StandardDeclaration)
StandardDeclaration(SourcePosition p, CallableNode* c, Statement* b)
......
......@@ -35,7 +35,8 @@ class Declarable {
kGenericList,
kTypeAlias,
kLabel,
kConstant
kConstant,
kModuleConstant
};
Kind kind() const { return kind_; }
bool IsMacro() const { return kind() == kMacro; }
......@@ -49,7 +50,10 @@ class Declarable {
bool IsMacroList() const { return kind() == kMacroList; }
bool IsGenericList() const { return kind() == kGenericList; }
bool IsConstant() const { return kind() == kConstant; }
bool IsValue() const { return IsVariable() || IsConstant() || IsParameter(); }
bool IsModuleConstant() const { return kind() == kModuleConstant; }
bool IsValue() const {
return IsVariable() || IsConstant() || IsParameter() || IsModuleConstant();
}
virtual const char* type_name() const { return "<<unknown>>"; }
protected:
......@@ -112,6 +116,18 @@ class Parameter : public Value {
std::string var_name_;
};
class ModuleConstant : public Value {
public:
DECLARE_DECLARABLE_BOILERPLATE(ModuleConstant, constant);
std::string value() const override { UNREACHABLE(); }
std::string RValue() const override { return name() + "()"; }
private:
friend class Declarations;
explicit ModuleConstant(const std::string& name, const Type* type)
: Value(Declarable::kModuleConstant, type, name) {}
};
class Variable : public Value {
public:
DECLARE_DECLARABLE_BOILERPLATE(Variable, variable);
......
......@@ -173,6 +173,12 @@ void DeclarationVisitor::Visit(TorqueMacroDeclaration* decl,
changed_vars);
}
void DeclarationVisitor::Visit(ConstDeclaration* decl) {
declarations()->DeclareModuleConstant(decl->name,
declarations()->GetType(decl->type));
Visit(decl->expression);
}
void DeclarationVisitor::Visit(StandardDeclaration* decl) {
Signature signature = MakeSignature(decl->callable->signature.get());
Visit(decl->callable, signature, decl->body);
......
......@@ -91,6 +91,7 @@ class DeclarationVisitor : public FileVisitor {
void Visit(CallableNode* decl, const Signature& signature, Statement* body);
void Visit(ConstDeclaration* decl);
void Visit(StandardDeclaration* decl);
void Visit(GenericDeclaration* decl);
void Visit(SpecializationDeclaration* decl);
......
......@@ -179,6 +179,18 @@ GenericList* Declarations::LookupGeneric(const std::string& name) {
return nullptr;
}
ModuleConstant* Declarations::LookupModuleConstant(const std::string& name) {
Declarable* declarable = Lookup(name);
if (declarable != nullptr) {
if (declarable->IsModuleConstant()) {
return ModuleConstant::cast(declarable);
}
ReportError(name + " is not a constant");
}
ReportError(std::string("constant \"") + name + "\" is not defined");
return nullptr;
}
const AbstractType* Declarations::DeclareAbstractType(
const std::string& name, const std::string& generated,
base::Optional<const AbstractType*> non_constexpr_version,
......@@ -309,6 +321,14 @@ void Declarations::DeclareConstant(const std::string& name, const Type* type,
Declare(name, std::unique_ptr<Declarable>(result));
}
ModuleConstant* Declarations::DeclareModuleConstant(const std::string& name,
const Type* type) {
CheckAlreadyDeclared(name, "module constant");
ModuleConstant* result = new ModuleConstant(name, type);
Declare(name, std::unique_ptr<Declarable>(result));
return result;
}
Generic* Declarations::DeclareGeneric(const std::string& name, Module* module,
GenericDeclaration* generic) {
auto previous = chain_.Lookup(name);
......
......@@ -67,6 +67,7 @@ class Declarations {
Label* LookupLabel(const std::string& name);
GenericList* LookupGeneric(const std::string& name);
ModuleConstant* LookupModuleConstant(const std::string& name);
const AbstractType* DeclareAbstractType(
const std::string& name, const std::string& generated,
......@@ -96,6 +97,8 @@ class Declarations {
void DeclareConstant(const std::string& name, const Type* type,
const std::string& value);
ModuleConstant* DeclareModuleConstant(const std::string& name,
const Type* type);
Generic* DeclareGeneric(const std::string& name, Module* module,
GenericDeclaration* generic);
......
......@@ -25,6 +25,12 @@ Signature FileVisitor::MakeSignature(const CallableNodeSignature* signature) {
return result;
}
Signature FileVisitor::MakeSignatureFromReturnType(
TypeExpression* return_type) {
Signature result{{}, {{}, false}, declarations()->GetType(return_type), {}};
return result;
}
void FileVisitor::QueueGenericSpecialization(
const SpecializationKey& key, CallableNode* callable,
const CallableNodeSignature* signature, base::Optional<Statement*> body) {
......
......@@ -66,6 +66,7 @@ class FileVisitor {
}
Signature MakeSignature(const CallableNodeSignature* signature);
Signature MakeSignatureFromReturnType(TypeExpression* return_type);
struct PendingSpecialization {
SpecializationKey key;
......
......@@ -164,6 +164,30 @@ void ImplementationVisitor::Visit(ModuleDeclaration* decl) {
module_ = saved_module;
}
void ImplementationVisitor::Visit(ConstDeclaration* decl) {
Signature signature = MakeSignatureFromReturnType(decl->type);
std::string name = decl->name;
header_out() << " ";
GenerateFunctionDeclaration(header_out(), "", name, signature, {});
header_out() << ";\n";
GenerateFunctionDeclaration(source_out(),
GetDSLAssemblerName(CurrentModule()) + "::", name,
signature, {});
source_out() << " {\n";
DCHECK(!signature.return_type->IsVoidOrNever());
VisitResult expression_result = Visit(decl->expression);
VisitResult return_result =
GenerateImplicitConvert(signature.return_type, expression_result);
GenerateIndent();
source_out() << "return " << return_result.RValue() << ";\n";
source_out() << "}\n\n";
}
void ImplementationVisitor::Visit(TorqueMacroDeclaration* decl,
const Signature& sig, Statement* body) {
Signature signature = MakeSignature(decl->signature.get());
......@@ -789,6 +813,10 @@ const Type* ImplementationVisitor::Visit(ReturnStatement* stmt) {
source_out() << "Return(" << return_result.RValue() << ");"
<< std::endl;
}
} else if (current_callable->IsModuleConstant()) {
Variable* var =
Variable::cast(declarations()->LookupValue(kReturnValueVariable));
GenerateAssignToVariable(var, return_result);
} else {
UNREACHABLE();
}
......@@ -1030,26 +1058,32 @@ void ImplementationVisitor::GenerateIndent() {
void ImplementationVisitor::GenerateMacroFunctionDeclaration(
std::ostream& o, const std::string& macro_prefix, Macro* macro) {
GenerateFunctionDeclaration(o, macro_prefix, macro->name(),
macro->signature(), macro->parameter_names());
}
void ImplementationVisitor::GenerateFunctionDeclaration(
std::ostream& o, const std::string& macro_prefix, const std::string& name,
const Signature& signature, const NameVector& parameter_names) {
if (global_context_.verbose()) {
std::cout << "generating source for declaration " << *macro << ""
std::cout << "generating source for declaration " << name << ""
<< std::endl;
}
// Quite a hack here. Make sure that TNode is namespace qualified if the
// macro name is also qualified.
std::string return_type_name(
macro->signature().return_type->GetGeneratedTypeName());
// macro/constant name is also qualified.
std::string return_type_name(signature.return_type->GetGeneratedTypeName());
if (macro_prefix != "" && (return_type_name.length() > 5) &&
(return_type_name.substr(0, 5) == "TNode")) {
o << "compiler::";
}
o << return_type_name;
o << " " << macro_prefix << macro->name() << "(";
o << " " << macro_prefix << name << "(";
DCHECK_EQ(macro->signature().types().size(), macro->parameter_names().size());
auto type_iterator = macro->signature().types().begin();
DCHECK_EQ(signature.types().size(), parameter_names.size());
auto type_iterator = signature.types().begin();
bool first = true;
for (const std::string& name : macro->parameter_names()) {
for (const std::string& name : parameter_names) {
if (!first) {
o << ", ";
}
......@@ -1062,7 +1096,7 @@ void ImplementationVisitor::GenerateMacroFunctionDeclaration(
first = false;
}
for (const LabelDeclaration& label_info : macro->signature().labels) {
for (const LabelDeclaration& label_info : signature.labels) {
Label* label = declarations()->LookupLabel(label_info.name);
if (!first) {
o << ", ";
......@@ -1700,11 +1734,8 @@ VisitResult ImplementationVisitor::GenerateImplicitConvert(
GetGeneratedCallableName(kFromConstexprMacroName, {destination_type});
return GenerateCall(name, {{source}, {}}, false);
} else if (IsAssignableFrom(destination_type, source.type())) {
if (source.declarable()) {
return VisitResult(destination_type, *source.declarable());
} else {
return VisitResult(destination_type, source.value());
}
source.SetType(destination_type);
return source;
} else {
std::stringstream s;
s << "cannot use expression of type " << *source.type()
......
......@@ -108,6 +108,7 @@ class ImplementationVisitor : public FileVisitor {
void Visit(ExternalRuntimeDeclaration* decl, const Signature& signature,
Statement* body) {}
void Visit(CallableNode* decl, const Signature& signature, Statement* body);
void Visit(ConstDeclaration* decl);
VisitResult Visit(CallExpression* expr, bool is_tail = false);
const Type* Visit(TailCallStatement* stmt);
......@@ -216,6 +217,11 @@ class ImplementationVisitor : public FileVisitor {
void GenerateMacroFunctionDeclaration(std::ostream& o,
const std::string& macro_prefix,
Macro* macro);
void GenerateFunctionDeclaration(std::ostream& o,
const std::string& macro_prefix,
const std::string& name,
const Signature& signature,
const NameVector& parameter_names);
VisitResult GenerateImplicitConvert(const Type* destination_type,
VisitResult source);
......
......@@ -249,12 +249,14 @@ bool operator<(const Type& a, const Type& b) {
}
VisitResult::VisitResult(const Type* type, const Value* declarable)
: type_(type), value_(declarable->value()), declarable_(declarable) {}
: type_(type), value_(), declarable_(declarable) {}
std::string VisitResult::LValue() const { return std::string("*") + value_; }
std::string VisitResult::LValue() const {
return std::string("*") + (declarable_ ? (*declarable_)->value() : value_);
}
std::string VisitResult::RValue() const {
return (declarable_) ? (*declarable_)->RValue() : value_;
return declarable_ ? (*declarable_)->RValue() : value_;
}
} // namespace torque
......
......@@ -299,9 +299,9 @@ class VisitResult {
const Type* type() const { return type_; }
// const std::string& variable() const { return variable_; }
base::Optional<const Value*> declarable() const { return declarable_; }
std::string value() const { return value_; }
std::string LValue() const;
std::string RValue() const;
void SetType(const Type* new_type) { type_ = new_type; }
private:
const Type* type_;
......
......@@ -200,6 +200,18 @@ TEST(TestHexLiteral) {
ft.Call();
}
TEST(TestModuleConstBindings) {
Isolate* isolate(CcTest::InitIsolateOnce());
CodeAssemblerTester asm_tester(isolate, 0);
TestBuiltinsFromDSLAssembler m(asm_tester.state());
{
m.TestModuleConstBindings();
m.Return(m.UndefinedConstant());
}
FunctionTester ft(asm_tester.GenerateCode(), 0);
ft.Call();
}
} // namespace compiler
} // namespace internal
} // namespace v8
......@@ -228,4 +228,14 @@ module test {
macro TestNewlineInString() {
Print('Hello, World!\n');
}
const kConstexprConst: constexpr int31 = 5;
const kIntptrConst: intptr = 4;
const kSmiConst: Smi = 3;
macro TestModuleConstBindings() {
check(kConstexprConst == Int32Constant(5));
check(kIntptrConst == 4);
check(kSmiConst == 3);
}
}
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