[torque] Make torque declarations order independent

Torque semantic analysis is now a four-stage process:

 1. The TypeDeclarationVisitor introduces a TypeAlias for every
    TypeDeclaration* (or derived) in the Torque source, but does
    not process the TypeDeclaration* itself.
 2. All aliases are resolved in a dependency respecting manner.
    This CL also changes struct member resolution to happen at
    this point already. Types for classes are created, but their
    members are not resolved to allow classes to mutually reference
    each other in their field types.
 3. 'value' declarations (macros, etc.) are processed.
 4. Members of classes are processed.

Bug: v8:7793
Change-Id: I46108555a5cdf30df03c5d4399ec786ee6cc6df4
Reviewed-on: https://chromium-review.googlesource.com/c/v8/v8/+/1584319
Commit-Queue: Sigurd Schneider <sigurds@chromium.org>
Reviewed-by: Tobias Tebbi <tebbi@chromium.org>
Cr-Commit-Position: refs/heads/master@{#61264}
This commit is contained in:
Sigurd Schneider 2019-05-07 10:38:44 +02:00 committed by Commit Bot
parent 7626fe352c
commit 70678d53a1
24 changed files with 886 additions and 691 deletions

View File

@ -912,11 +912,7 @@ action("postmortem-metadata") {
}
torque_files = [
"src/builtins/base.tq",
"src/builtins/growable-fixed-array.tq",
"src/builtins/frames.tq",
"src/builtins/arguments.tq",
"src/builtins/array.tq",
"src/builtins/array-copywithin.tq",
"src/builtins/array-every.tq",
"src/builtins/array-filter.tq",
@ -925,37 +921,40 @@ torque_files = [
"src/builtins/array-foreach.tq",
"src/builtins/array-join.tq",
"src/builtins/array-lastindexof.tq",
"src/builtins/array-of.tq",
"src/builtins/array-map.tq",
"src/builtins/array-reduce.tq",
"src/builtins/array-of.tq",
"src/builtins/array-reduce-right.tq",
"src/builtins/array-reduce.tq",
"src/builtins/array-reverse.tq",
"src/builtins/array-shift.tq",
"src/builtins/array-slice.tq",
"src/builtins/array-some.tq",
"src/builtins/array-splice.tq",
"src/builtins/array-unshift.tq",
"src/builtins/array.tq",
"src/builtins/base.tq",
"src/builtins/collections.tq",
"src/builtins/data-view.tq",
"src/builtins/extras-utils.tq",
"src/builtins/frames.tq",
"src/builtins/growable-fixed-array.tq",
"src/builtins/internal-coverage.tq",
"src/builtins/iterator.tq",
"src/builtins/math.tq",
"src/builtins/object-fromentries.tq",
"src/builtins/proxy.tq",
"src/builtins/proxy-constructor.tq",
"src/builtins/proxy-get-property.tq",
"src/builtins/proxy-revocable.tq",
"src/builtins/proxy-revoke.tq",
"src/builtins/regexp.tq",
"src/builtins/proxy.tq",
"src/builtins/regexp-replace.tq",
"src/builtins/regexp.tq",
"src/builtins/string.tq",
"src/builtins/string-endswith.tq",
"src/builtins/string-html.tq",
"src/builtins/string-iterator.tq",
"src/builtins/string-repeat.tq",
"src/builtins/string-startswith.tq",
"src/builtins/typed-array.tq",
"src/builtins/typed-array-createtypedarray.tq",
"src/builtins/typed-array-every.tq",
"src/builtins/typed-array-filter.tq",
@ -967,6 +966,7 @@ torque_files = [
"src/builtins/typed-array-slice.tq",
"src/builtins/typed-array-some.tq",
"src/builtins/typed-array-subarray.tq",
"src/builtins/typed-array.tq",
"src/objects/intl-objects.tq",
"test/torque/test-torque.tq",
"third_party/v8/builtins/array-sort.tq",
@ -3297,6 +3297,7 @@ v8_source_set("torque_base") {
"src/torque/ast.h",
"src/torque/cfg.cc",
"src/torque/cfg.h",
"src/torque/constants.h",
"src/torque/contextual.h",
"src/torque/csa-generator.cc",
"src/torque/csa-generator.h",
@ -3308,8 +3309,6 @@ v8_source_set("torque_base") {
"src/torque/declarations.h",
"src/torque/earley-parser.cc",
"src/torque/earley-parser.h",
"src/torque/file-visitor.cc",
"src/torque/file-visitor.h",
"src/torque/global-context.h",
"src/torque/implementation-visitor.cc",
"src/torque/implementation-visitor.h",
@ -3325,6 +3324,8 @@ v8_source_set("torque_base") {
"src/torque/torque-parser.h",
"src/torque/type-oracle.cc",
"src/torque/type-oracle.h",
"src/torque/type-visitor.cc",
"src/torque/type-visitor.h",
"src/torque/types.cc",
"src/torque/types.h",
"src/torque/utils.cc",

View File

@ -11,6 +11,7 @@
#include <vector>
#include "src/base/optional.h"
#include "src/torque/constants.h"
#include "src/torque/source-positions.h"
namespace v8 {
@ -61,15 +62,18 @@ namespace torque {
V(VarDeclarationStatement) \
V(GotoStatement)
#define AST_TYPE_DECLARATION_NODE_KIND_LIST(V) \
V(AbstractTypeDeclaration) \
V(TypeAliasDeclaration) \
V(ClassDeclaration) \
V(StructDeclaration)
#define AST_DECLARATION_NODE_KIND_LIST(V) \
V(TypeDeclaration) \
V(TypeAliasDeclaration) \
AST_TYPE_DECLARATION_NODE_KIND_LIST(V) \
V(StandardDeclaration) \
V(GenericDeclaration) \
V(SpecializationDeclaration) \
V(ExternConstDeclaration) \
V(ClassDeclaration) \
V(StructDeclaration) \
V(NamespaceDeclaration) \
V(ConstDeclaration) \
V(CppIncludeDeclaration)
@ -435,10 +439,10 @@ struct BasicTypeExpression : TypeExpression {
DEFINE_AST_NODE_LEAF_BOILERPLATE(BasicTypeExpression)
BasicTypeExpression(SourcePosition pos,
std::vector<std::string> namespace_qualification,
bool is_constexpr, std::string name)
std::string name)
: TypeExpression(kKind, pos),
namespace_qualification(std::move(namespace_qualification)),
is_constexpr(is_constexpr),
is_constexpr(IsConstexprName(name)),
name(std::move(name)) {}
std::vector<std::string> namespace_qualification;
bool is_constexpr;
@ -665,30 +669,33 @@ struct BlockStatement : Statement {
};
struct TypeDeclaration : Declaration {
DEFINE_AST_NODE_LEAF_BOILERPLATE(TypeDeclaration)
TypeDeclaration(SourcePosition pos, Identifier* name, bool transient,
base::Optional<Identifier*> extends,
base::Optional<std::string> generates,
base::Optional<std::string> constexpr_generates)
: Declaration(kKind, pos),
name(name),
DEFINE_AST_NODE_INNER_BOILERPLATE(TypeDeclaration)
TypeDeclaration(Kind kKind, SourcePosition pos, Identifier* name)
: Declaration(kKind, pos), name(name) {}
Identifier* name;
};
struct AbstractTypeDeclaration : TypeDeclaration {
DEFINE_AST_NODE_LEAF_BOILERPLATE(AbstractTypeDeclaration)
AbstractTypeDeclaration(SourcePosition pos, Identifier* name, bool transient,
base::Optional<Identifier*> extends,
base::Optional<std::string> generates)
: TypeDeclaration(kKind, pos, name),
is_constexpr(IsConstexprName(name->value)),
transient(transient),
extends(extends),
generates(std::move(generates)),
constexpr_generates(std::move(constexpr_generates)) {}
Identifier* name;
generates(std::move(generates)) {}
bool is_constexpr;
bool transient;
base::Optional<Identifier*> extends;
base::Optional<std::string> generates;
base::Optional<std::string> constexpr_generates;
};
struct TypeAliasDeclaration : Declaration {
struct TypeAliasDeclaration : TypeDeclaration {
DEFINE_AST_NODE_LEAF_BOILERPLATE(TypeAliasDeclaration)
TypeAliasDeclaration(SourcePosition pos, Identifier* name,
TypeExpression* type)
: Declaration(kKind, pos), name(name), type(type) {}
Identifier* name;
: TypeDeclaration(kKind, pos, name), type(type) {}
TypeExpression* type;
};
@ -895,21 +902,19 @@ struct ExternConstDeclaration : Declaration {
std::string literal;
};
struct StructDeclaration : Declaration {
struct StructDeclaration : TypeDeclaration {
DEFINE_AST_NODE_LEAF_BOILERPLATE(StructDeclaration)
StructDeclaration(SourcePosition pos, Identifier* name,
std::vector<Declaration*> methods,
std::vector<StructFieldExpression> fields)
: Declaration(kKind, pos),
name(name),
: TypeDeclaration(kKind, pos, name),
methods(std::move(methods)),
fields(std::move(fields)) {}
Identifier* name;
std::vector<Declaration*> methods;
std::vector<StructFieldExpression> fields;
};
struct ClassDeclaration : Declaration {
struct ClassDeclaration : TypeDeclaration {
DEFINE_AST_NODE_LEAF_BOILERPLATE(ClassDeclaration)
ClassDeclaration(SourcePosition pos, Identifier* name, bool is_extern,
bool generate_print, bool transient,
@ -917,8 +922,7 @@ struct ClassDeclaration : Declaration {
base::Optional<std::string> generates,
std::vector<Declaration*> methods,
std::vector<ClassFieldExpression> fields)
: Declaration(kKind, pos),
name(name),
: TypeDeclaration(kKind, pos, name),
is_extern(is_extern),
generate_print(generate_print),
transient(transient),
@ -926,7 +930,6 @@ struct ClassDeclaration : Declaration {
generates(std::move(generates)),
methods(std::move(methods)),
fields(std::move(fields)) {}
Identifier* name;
bool is_extern;
bool generate_print;
bool transient;

64
src/torque/constants.h Normal file
View File

@ -0,0 +1,64 @@
// Copyright 2019 the V8 project authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#ifndef V8_TORQUE_CONSTANTS_H_
#define V8_TORQUE_CONSTANTS_H_
#include <string>
namespace v8 {
namespace internal {
namespace torque {
static const char* const CONSTEXPR_TYPE_PREFIX = "constexpr ";
static const char* const NEVER_TYPE_STRING = "never";
static const char* const CONSTEXPR_BOOL_TYPE_STRING = "constexpr bool";
static const char* const CONSTEXPR_INTPTR_TYPE_STRING = "constexpr intptr";
static const char* const BOOL_TYPE_STRING = "bool";
static const char* const VOID_TYPE_STRING = "void";
static const char* const ARGUMENTS_TYPE_STRING = "Arguments";
static const char* const CONTEXT_TYPE_STRING = "Context";
static const char* const MAP_TYPE_STRING = "Map";
static const char* const OBJECT_TYPE_STRING = "Object";
static const char* const HEAP_OBJECT_TYPE_STRING = "HeapObject";
static const char* const JSOBJECT_TYPE_STRING = "JSObject";
static const char* const SMI_TYPE_STRING = "Smi";
static const char* const TAGGED_TYPE_STRING = "Tagged";
static const char* const RAWPTR_TYPE_STRING = "RawPtr";
static const char* const CONST_STRING_TYPE_STRING = "constexpr string";
static const char* const STRING_TYPE_STRING = "String";
static const char* const NUMBER_TYPE_STRING = "Number";
static const char* const BUILTIN_POINTER_TYPE_STRING = "BuiltinPtr";
static const char* const INTPTR_TYPE_STRING = "intptr";
static const char* const UINTPTR_TYPE_STRING = "uintptr";
static const char* const INT32_TYPE_STRING = "int32";
static const char* const UINT32_TYPE_STRING = "uint32";
static const char* const INT16_TYPE_STRING = "int16";
static const char* const UINT16_TYPE_STRING = "uint16";
static const char* const INT8_TYPE_STRING = "int8";
static const char* const UINT8_TYPE_STRING = "uint8";
static const char* const FLOAT64_TYPE_STRING = "float64";
static const char* const CONST_INT31_TYPE_STRING = "constexpr int31";
static const char* const CONST_INT32_TYPE_STRING = "constexpr int32";
static const char* const CONST_FLOAT64_TYPE_STRING = "constexpr float64";
inline bool IsConstexprName(const std::string& name) {
return name.substr(0, strlen(CONSTEXPR_TYPE_PREFIX)) == CONSTEXPR_TYPE_PREFIX;
}
inline std::string GetNonConstexprName(const std::string& name) {
if (!IsConstexprName(name)) return name;
return name.substr(strlen(CONSTEXPR_TYPE_PREFIX));
}
inline std::string GetConstexprName(const std::string& name) {
if (IsConstexprName(name)) return name;
return CONSTEXPR_TYPE_PREFIX + name;
}
} // namespace torque
} // namespace internal
} // namespace v8
#endif // V8_TORQUE_CONSTANTS_H_

View File

@ -7,6 +7,7 @@
#include "src/torque/declarable.h"
#include "src/torque/global-context.h"
#include "src/torque/type-visitor.h"
namespace v8 {
namespace internal {
@ -126,6 +127,22 @@ bool Namespace::IsDefaultNamespace() const {
bool Namespace::IsTestNamespace() const { return name() == kTestNamespaceName; }
const Type* TypeAlias::Resolve() const {
if (!type_) {
CurrentScope::Scope scope_activator(ParentScope());
CurrentSourcePosition::Scope position_activator(Position());
TypeDeclaration* decl = *delayed_;
if (being_resolved_) {
std::stringstream s;
s << "Cannot create type " << decl->name->value
<< " due to circular dependencies.";
ReportError(s.str());
}
type_ = TypeVisitor::ComputeType(decl);
}
return *type_;
}
} // namespace torque
} // namespace internal
} // namespace v8

View File

@ -459,7 +459,11 @@ class TypeAlias : public Declarable {
public:
DECLARE_DECLARABLE_BOILERPLATE(TypeAlias, type_alias)
const Type* type() const { return type_; }
const Type* type() const {
if (type_) return *type_;
return Resolve();
}
const Type* Resolve() const;
bool IsRedeclaration() const { return redeclaration_; }
SourcePosition GetDeclarationPosition() const {
return declaration_position_;
@ -467,6 +471,8 @@ class TypeAlias : public Declarable {
private:
friend class Declarations;
friend class TypeVisitor;
explicit TypeAlias(
const Type* type, bool redeclaration,
SourcePosition declaration_position = SourcePosition::Invalid())
@ -474,8 +480,17 @@ class TypeAlias : public Declarable {
type_(type),
redeclaration_(redeclaration),
declaration_position_(declaration_position) {}
explicit TypeAlias(
TypeDeclaration* type, bool redeclaration,
SourcePosition declaration_position = SourcePosition::Invalid())
: Declarable(Declarable::kTypeAlias),
delayed_(type),
redeclaration_(redeclaration),
declaration_position_(declaration_position) {}
const Type* type_;
mutable bool being_resolved_ = false;
mutable base::Optional<TypeDeclaration*> delayed_;
mutable base::Optional<const Type*> type_;
bool redeclaration_;
const SourcePosition declaration_position_;
};

View File

@ -4,13 +4,40 @@
#include "src/torque/declaration-visitor.h"
#include "src/globals.h"
#include "src/torque/ast.h"
#include "src/torque/server-data.h"
#include "src/torque/type-visitor.h"
namespace v8 {
namespace internal {
namespace torque {
Namespace* GetOrCreateNamespace(const std::string& name) {
std::vector<Namespace*> existing_namespaces = FilterDeclarables<Namespace>(
Declarations::TryLookupShallow(QualifiedName(name)));
if (existing_namespaces.empty()) {
return Declarations::DeclareNamespace(name);
}
DCHECK_EQ(1, existing_namespaces.size());
return existing_namespaces.front();
}
void TypeDeclarationVisitor::Predeclare(Declaration* decl) {
CurrentSourcePosition::Scope scope(decl->pos);
switch (decl->kind) {
#define ENUM_ITEM(name) \
case AstNode::Kind::k##name: \
return Predeclare(name::cast(decl));
AST_TYPE_DECLARATION_NODE_KIND_LIST(ENUM_ITEM)
#undef ENUM_ITEM
case AstNode::Kind::kNamespaceDeclaration:
return Predeclare(NamespaceDeclaration::cast(decl));
default:
// This visitor only processes type declaration nodes.
break;
}
}
void DeclarationVisitor::Visit(Declaration* decl) {
CurrentSourcePosition::Scope scope(decl->pos);
switch (decl->kind) {
@ -168,11 +195,12 @@ void DeclarationVisitor::Visit(IntrinsicDeclaration* decl,
void DeclarationVisitor::Visit(ConstDeclaration* decl) {
Declarations::DeclareNamespaceConstant(
decl->name, Declarations::GetType(decl->type), decl->expression);
decl->name, TypeVisitor::ComputeType(decl->type), decl->expression);
}
void DeclarationVisitor::Visit(StandardDeclaration* decl) {
Signature signature = MakeSignature(decl->callable->signature.get());
Signature signature =
TypeVisitor::MakeSignature(decl->callable->signature.get());
Visit(decl->callable, signature, decl->body);
}
@ -192,10 +220,12 @@ void DeclarationVisitor::Visit(SpecializationDeclaration* decl) {
// Find the matching generic specialization based on the concrete parameter
// list.
Generic* matching_generic = nullptr;
Signature signature_with_types = MakeSignature(decl->signature.get());
Signature signature_with_types =
TypeVisitor::MakeSignature(decl->signature.get());
for (Generic* generic : generic_list) {
Signature generic_signature_with_types = MakeSpecializedSignature(
SpecializationKey{generic, GetTypeVector(decl->generic_parameters)});
Signature generic_signature_with_types =
MakeSpecializedSignature(SpecializationKey{
generic, TypeVisitor::ComputeTypeVector(decl->generic_parameters)});
if (signature_with_types.HasSameTypesAs(generic_signature_with_types,
ParameterMode::kIgnoreImplicit)) {
if (matching_generic != nullptr) {
@ -223,19 +253,20 @@ void DeclarationVisitor::Visit(SpecializationDeclaration* decl) {
for (Generic* generic : generic_list) {
stream << "\n "
<< MakeSpecializedSignature(SpecializationKey{
generic, GetTypeVector(decl->generic_parameters)});
generic,
TypeVisitor::ComputeTypeVector(decl->generic_parameters)});
}
ReportError(stream.str());
}
Specialize(SpecializationKey{matching_generic,
GetTypeVector(decl->generic_parameters)},
Specialize(SpecializationKey{matching_generic, TypeVisitor::ComputeTypeVector(
decl->generic_parameters)},
matching_generic->declaration()->callable, decl->signature.get(),
decl->body);
}
void DeclarationVisitor::Visit(ExternConstDeclaration* decl) {
const Type* type = Declarations::GetType(decl->type);
const Type* type = TypeVisitor::ComputeType(decl->type);
if (!type->IsConstexpr()) {
std::stringstream stream;
stream << "extern constants must have constexpr type, but found: \""
@ -246,123 +277,10 @@ void DeclarationVisitor::Visit(ExternConstDeclaration* decl) {
Declarations::DeclareExternConstant(decl->name, type, decl->literal);
}
void DeclarationVisitor::DeclareMethods(
AggregateType* container_type, const std::vector<Declaration*>& methods) {
// Declare the class' methods
for (auto declaration : methods) {
CurrentSourcePosition::Scope pos_scope(declaration->pos);
StandardDeclaration* standard_declaration =
StandardDeclaration::DynamicCast(declaration);
DCHECK(standard_declaration);
TorqueMacroDeclaration* method =
TorqueMacroDeclaration::DynamicCast(standard_declaration->callable);
Signature signature = MakeSignature(method->signature.get());
signature.parameter_names.insert(
signature.parameter_names.begin() + signature.implicit_count,
MakeNode<Identifier>(kThisParameterName));
Statement* body = *(standard_declaration->body);
std::string method_name(method->name);
signature.parameter_types.types.insert(
signature.parameter_types.types.begin() + signature.implicit_count,
container_type);
Declarations::CreateMethod(container_type, method_name, signature, false,
body);
}
}
void DeclarationVisitor::Visit(StructDeclaration* decl) {
StructType* struct_type = Declarations::DeclareStruct(decl->name);
struct_declarations_.push_back(
std::make_tuple(CurrentScope::Get(), decl, struct_type));
}
void DeclarationVisitor::Visit(ClassDeclaration* decl) {
ClassType* new_class;
if (decl->is_extern) {
if (!decl->super) {
ReportError("Extern class must extend another type.");
}
const Type* super_type = Declarations::GetType(*decl->super);
if (super_type != TypeOracle::GetTaggedType()) {
const ClassType* super_class = ClassType::DynamicCast(super_type);
if (!super_class) {
ReportError(
"class \"", decl->name->value,
"\" must extend either Tagged or an already declared class");
}
}
// The generates clause must create a TNode<>
std::string generates = decl->name->value;
if (decl->generates) {
generates = *decl->generates;
if (generates.length() < 7 || generates.substr(0, 6) != "TNode<" ||
generates.substr(generates.length() - 1, 1) != ">") {
ReportError("generated type \"", generates,
"\" should be of the form \"TNode<...>\"");
}
generates = generates.substr(6, generates.length() - 7);
}
new_class = Declarations::DeclareClass(
super_type, decl->name, decl->is_extern, decl->generate_print,
decl->transient, generates);
} else {
if (decl->super) {
ReportError("Only extern classes can inherit.");
}
if (decl->generates) {
ReportError("Only extern classes can specify a generated type.");
}
new_class = Declarations::DeclareClass(
TypeOracle::GetTaggedType(), decl->name, decl->is_extern,
decl->generate_print, decl->transient, "FixedArray");
}
GlobalContext::RegisterClass(decl->name->value, new_class);
class_declarations_.push_back(
std::make_tuple(CurrentScope::Get(), decl, new_class));
}
void DeclarationVisitor::Visit(CppIncludeDeclaration* decl) {
GlobalContext::AddCppInclude(decl->include_path);
}
void DeclarationVisitor::Visit(TypeDeclaration* decl) {
std::string generates = decl->generates ? *decl->generates : std::string("");
if (decl->generates) {
if (generates.length() < 7 || generates.substr(0, 6) != "TNode<" ||
generates.substr(generates.length() - 1, 1) != ">") {
ReportError("generated type \"", generates,
"\" should be of the form \"TNode<...>\"");
}
generates = generates.substr(6, generates.length() - 7);
}
const AbstractType* type = Declarations::DeclareAbstractType(
decl->name, decl->transient, generates, {}, decl->extends);
if (decl->constexpr_generates) {
if (decl->transient) {
ReportError("cannot declare a transient type that is also constexpr");
}
// DeclareAbstractType expects an Identifier*. A new one is created from the
// declaration, and the SourcePosition copied from the original name.
Identifier* constexpr_name =
MakeNode<Identifier>(CONSTEXPR_TYPE_PREFIX + decl->name->value);
constexpr_name->pos = decl->name->pos;
base::Optional<Identifier*> constexpr_extends;
if (decl->extends) {
constexpr_extends =
MakeNode<Identifier>(CONSTEXPR_TYPE_PREFIX + (*decl->extends)->value);
(*constexpr_extends)->pos = (*decl->extends)->pos;
}
Declarations::DeclareAbstractType(constexpr_name, false,
*decl->constexpr_generates, type,
constexpr_extends);
}
}
void DeclarationVisitor::DeclareSpecializedTypes(const SpecializationKey& key) {
size_t i = 0;
const std::size_t generic_parameter_count =
@ -378,7 +296,7 @@ void DeclarationVisitor::DeclareSpecializedTypes(const SpecializationKey& key) {
for (auto type : key.specialized_types) {
Identifier* generic_type_name =
key.generic->declaration()->generic_parameters[i++];
Declarations::DeclareType(generic_type_name, type, true);
Declarations::DeclareType(generic_type_name, type);
}
}
@ -390,7 +308,8 @@ Signature DeclarationVisitor::MakeSpecializedSignature(
Namespace tmp_namespace("_tmp");
CurrentScope::Scope tmp_namespace_scope(&tmp_namespace);
DeclareSpecializedTypes(key);
return MakeSignature(key.generic->declaration()->callable->signature.get());
return TypeVisitor::MakeSignature(
key.generic->declaration()->callable->signature.get());
}
Callable* DeclarationVisitor::SpecializeImplicit(const SpecializationKey& key) {
@ -433,8 +352,8 @@ Callable* DeclarationVisitor::Specialize(
" with types <", key.specialized_types, ">");
}
Signature type_signature =
signature ? MakeSignature(*signature) : MakeSpecializedSignature(key);
Signature type_signature = signature ? TypeVisitor::MakeSignature(*signature)
: MakeSpecializedSignature(key);
std::string generated_name = Declarations::GetGeneratedCallableName(
declaration->name, key.specialized_types);
@ -463,161 +382,13 @@ Callable* DeclarationVisitor::Specialize(
return callable;
}
void DeclarationVisitor::FinalizeStructFieldsAndMethods(
StructType* struct_type, StructDeclaration* struct_declaration) {
size_t offset = 0;
for (auto& field : struct_declaration->fields) {
CurrentSourcePosition::Scope position_activator(
field.name_and_type.type->pos);
const Type* field_type = Declarations::GetType(field.name_and_type.type);
struct_type->RegisterField({field.name_and_type.name->pos,
struct_type,
base::nullopt,
{field.name_and_type.name->value, field_type},
offset,
false,
field.const_qualified});
offset += LoweredSlotCount(field_type);
}
CurrentSourcePosition::Scope position_activator(struct_declaration->pos);
DeclareMethods(struct_type, struct_declaration->methods);
}
void DeclarationVisitor::FinalizeClassFieldsAndMethods(
ClassType* class_type, ClassDeclaration* class_declaration) {
const ClassType* super_class = class_type->GetSuperClass();
size_t class_offset = super_class ? super_class->size() : 0;
bool seen_indexed_field = false;
for (ClassFieldExpression& field_expression : class_declaration->fields) {
CurrentSourcePosition::Scope position_activator(
field_expression.name_and_type.type->pos);
const Type* field_type =
Declarations::GetType(field_expression.name_and_type.type);
if (!class_declaration->is_extern) {
if (!field_type->IsSubtypeOf(TypeOracle::GetTaggedType())) {
ReportError("non-extern classes do not support untagged fields");
}
if (field_expression.weak) {
ReportError("non-extern classes do not support weak fields");
}
void TypeDeclarationVisitor::ResolvePredeclarations() {
for (auto& p : GlobalContext::AllDeclarables()) {
if (const TypeAlias* alias = TypeAlias::DynamicCast(p.get())) {
CurrentScope::Scope scope_activator(alias->ParentScope());
CurrentSourcePosition::Scope position_activator(alias->Position());
alias->Resolve();
}
if (field_expression.index) {
if (seen_indexed_field ||
(super_class && super_class->HasIndexedField())) {
ReportError(
"only one indexable field is currently supported per class");
}
seen_indexed_field = true;
const Field* index_field =
&(class_type->LookupField(*field_expression.index));
class_type->RegisterField(
{field_expression.name_and_type.name->pos,
class_type,
index_field,
{field_expression.name_and_type.name->value, field_type},
class_offset,
field_expression.weak,
field_expression.const_qualified});
} else {
if (seen_indexed_field) {
ReportError("cannot declare non-indexable field \"",
field_expression.name_and_type.name,
"\" after an indexable field "
"declaration");
}
const Field& field = class_type->RegisterField(
{field_expression.name_and_type.name->pos,
class_type,
base::nullopt,
{field_expression.name_and_type.name->value, field_type},
class_offset,
field_expression.weak,
field_expression.const_qualified});
size_t field_size;
std::string size_string;
std::string machine_type;
std::tie(field_size, size_string, machine_type) =
field.GetFieldSizeInformation();
// Our allocations don't support alignments beyond kTaggedSize.
size_t alignment = std::min(size_t{kTaggedSize}, field_size);
if (class_offset % alignment != 0) {
ReportError("field ", field_expression.name_and_type.name,
" at offset ", class_offset, " is not ", alignment,
"-byte aligned.");
}
class_offset += field_size;
}
}
class_type->SetSize(class_offset);
// For each field, construct AST snippits that implement a CSA accessor
// function and define a corresponding '.field' operator. The
// implementation iterator will turn the snippits into code.
for (auto& field : class_type->fields()) {
if (field.index) continue;
CurrentSourcePosition::Scope position_activator(field.pos);
IdentifierExpression* parameter =
MakeNode<IdentifierExpression>(MakeNode<Identifier>(std::string{"o"}));
// Load accessor
std::string camel_field_name = CamelifyString(field.name_and_type.name);
std::string load_macro_name =
"Load" + class_type->name() + camel_field_name;
Signature load_signature;
load_signature.parameter_names.push_back(MakeNode<Identifier>("o"));
load_signature.parameter_types.types.push_back(class_type);
load_signature.parameter_types.var_args = false;
load_signature.return_type = field.name_and_type.type;
Statement* load_body =
MakeNode<ReturnStatement>(MakeNode<FieldAccessExpression>(
parameter, MakeNode<Identifier>(field.name_and_type.name)));
Declarations::DeclareMacro(load_macro_name, base::nullopt, load_signature,
false, load_body, base::nullopt, false);
// Store accessor
IdentifierExpression* value = MakeNode<IdentifierExpression>(
std::vector<std::string>{}, MakeNode<Identifier>(std::string{"v"}));
std::string store_macro_name =
"Store" + class_type->name() + camel_field_name;
Signature store_signature;
store_signature.parameter_names.push_back(MakeNode<Identifier>("o"));
store_signature.parameter_names.push_back(MakeNode<Identifier>("v"));
store_signature.parameter_types.types.push_back(class_type);
store_signature.parameter_types.types.push_back(field.name_and_type.type);
store_signature.parameter_types.var_args = false;
// TODO(danno): Store macros probably should return their value argument
store_signature.return_type = TypeOracle::GetVoidType();
Statement* store_body =
MakeNode<ExpressionStatement>(MakeNode<AssignmentExpression>(
MakeNode<FieldAccessExpression>(
parameter, MakeNode<Identifier>(field.name_and_type.name)),
value));
Declarations::DeclareMacro(store_macro_name, base::nullopt, store_signature,
false, store_body, base::nullopt, false);
}
DeclareMethods(class_type, class_declaration->methods);
}
void DeclarationVisitor::FinalizeStructsAndClasses() {
for (auto current_struct_info : struct_declarations_) {
Scope* scope;
StructDeclaration* struct_declaration;
StructType* struct_type;
std::tie(scope, struct_declaration, struct_type) = current_struct_info;
CurrentScope::Scope scope_activator(scope);
CurrentSourcePosition::Scope position_activator(struct_declaration->pos);
FinalizeStructFieldsAndMethods(struct_type, struct_declaration);
}
for (auto current_class_info : class_declarations_) {
Scope* scope;
ClassDeclaration* class_declaration;
ClassType* class_type;
std::tie(scope, class_declaration, class_type) = current_class_info;
CurrentScope::Scope scope_activator(scope);
CurrentSourcePosition::Scope position_activator(class_declaration->pos);
FinalizeClassFieldsAndMethods(class_type, class_declaration);
}
}

View File

@ -10,7 +10,6 @@
#include "src/base/macros.h"
#include "src/torque/declarations.h"
#include "src/torque/file-visitor.h"
#include "src/torque/global-context.h"
#include "src/torque/types.h"
#include "src/torque/utils.h"
@ -19,94 +18,87 @@ namespace v8 {
namespace internal {
namespace torque {
class DeclarationVisitor : public FileVisitor {
Namespace* GetOrCreateNamespace(const std::string& name);
class TypeDeclarationVisitor {
public:
void Visit(Ast* ast) {
static void Predeclare(Ast* ast) {
CurrentScope::Scope current_namespace(GlobalContext::GetDefaultNamespace());
for (Declaration* child : ast->declarations()) Predeclare(child);
}
static void ResolvePredeclarations();
private:
static void Predeclare(Declaration* decl);
static void Predeclare(NamespaceDeclaration* decl) {
CurrentScope::Scope current_scope(GetOrCreateNamespace(decl->name));
for (Declaration* child : decl->declarations) Predeclare(child);
}
static void Predeclare(TypeDeclaration* decl) {
Declarations::PredeclareTypeAlias(decl->name, decl, false);
}
};
class DeclarationVisitor {
public:
static void Visit(Ast* ast) {
CurrentScope::Scope current_namespace(GlobalContext::GetDefaultNamespace());
for (Declaration* child : ast->declarations()) Visit(child);
}
void Visit(Declaration* decl);
Namespace* GetOrCreateNamespace(const std::string& name) {
std::vector<Namespace*> existing_namespaces = FilterDeclarables<Namespace>(
Declarations::TryLookupShallow(QualifiedName(name)));
if (existing_namespaces.empty()) {
return Declarations::DeclareNamespace(name);
}
DCHECK_EQ(1, existing_namespaces.size());
return existing_namespaces.front();
}
void Visit(NamespaceDeclaration* decl) {
static void Visit(Declaration* decl);
static void Visit(NamespaceDeclaration* decl) {
CurrentScope::Scope current_scope(GetOrCreateNamespace(decl->name));
for (Declaration* child : decl->declarations) Visit(child);
}
void Visit(TypeDeclaration* decl);
void DeclareMethods(AggregateType* container,
const std::vector<Declaration*>& methods);
void Visit(StructDeclaration* decl);
void Visit(ClassDeclaration* decl);
void Visit(TypeAliasDeclaration* decl) {
const Type* type = Declarations::GetType(decl->type);
type->AddAlias(decl->name->value);
Declarations::DeclareType(decl->name, type, true);
static void Visit(TypeDeclaration* decl) {
// Looking up the type will trigger type computation; this ensures errors
// are reported even if the type is unused.
Declarations::LookupType(decl->name);
}
Builtin* CreateBuiltin(BuiltinDeclaration* decl, std::string external_name,
std::string readable_name, Signature signature,
base::Optional<Statement*> body);
void Visit(ExternalBuiltinDeclaration* decl, const Signature& signature,
base::Optional<Statement*> body) {
static Builtin* CreateBuiltin(BuiltinDeclaration* decl,
std::string external_name,
std::string readable_name, Signature signature,
base::Optional<Statement*> body);
static void Visit(ExternalBuiltinDeclaration* decl,
const Signature& signature,
base::Optional<Statement*> body) {
Declarations::Declare(
decl->name,
CreateBuiltin(decl, decl->name, decl->name, signature, base::nullopt));
}
void Visit(ExternalRuntimeDeclaration* decl, const Signature& sig,
base::Optional<Statement*> body);
void Visit(ExternalMacroDeclaration* decl, const Signature& sig,
base::Optional<Statement*> body);
void Visit(TorqueBuiltinDeclaration* decl, const Signature& signature,
base::Optional<Statement*> body);
void Visit(TorqueMacroDeclaration* decl, const Signature& signature,
base::Optional<Statement*> body);
void Visit(IntrinsicDeclaration* decl, const Signature& signature,
base::Optional<Statement*> body);
static void Visit(ExternalRuntimeDeclaration* decl, const Signature& sig,
base::Optional<Statement*> body);
static void Visit(ExternalMacroDeclaration* decl, const Signature& sig,
base::Optional<Statement*> body);
static void Visit(TorqueBuiltinDeclaration* decl, const Signature& signature,
base::Optional<Statement*> body);
static void Visit(TorqueMacroDeclaration* decl, const Signature& signature,
base::Optional<Statement*> body);
static void Visit(IntrinsicDeclaration* decl, const Signature& signature,
base::Optional<Statement*> body);
void Visit(CallableNode* decl, const Signature& signature,
base::Optional<Statement*> body);
static void Visit(CallableNode* decl, const Signature& signature,
base::Optional<Statement*> body);
void Visit(ConstDeclaration* decl);
void Visit(StandardDeclaration* decl);
void Visit(GenericDeclaration* decl);
void Visit(SpecializationDeclaration* decl);
void Visit(ExternConstDeclaration* decl);
void Visit(CppIncludeDeclaration* decl);
static void Visit(ConstDeclaration* decl);
static void Visit(StandardDeclaration* decl);
static void Visit(GenericDeclaration* decl);
static void Visit(SpecializationDeclaration* decl);
static void Visit(ExternConstDeclaration* decl);
static void Visit(CppIncludeDeclaration* decl);
Signature MakeSpecializedSignature(const SpecializationKey& key);
Callable* SpecializeImplicit(const SpecializationKey& key);
Callable* Specialize(const SpecializationKey& key, CallableNode* declaration,
base::Optional<const CallableNodeSignature*> signature,
base::Optional<Statement*> body);
void FinalizeStructsAndClasses();
static Signature MakeSpecializedSignature(const SpecializationKey& key);
static Callable* SpecializeImplicit(const SpecializationKey& key);
static Callable* Specialize(
const SpecializationKey& key, CallableNode* declaration,
base::Optional<const CallableNodeSignature*> signature,
base::Optional<Statement*> body);
private:
void DeclareSpecializedTypes(const SpecializationKey& key);
void FinalizeStructFieldsAndMethods(StructType* struct_type,
StructDeclaration* struct_declaration);
void FinalizeClassFieldsAndMethods(ClassType* class_type,
ClassDeclaration* class_declaration);
std::vector<std::tuple<Scope*, StructDeclaration*, StructType*>>
struct_declarations_;
std::vector<std::tuple<Scope*, ClassDeclaration*, ClassType*>>
class_declarations_;
static void DeclareSpecializedTypes(const SpecializationKey& key);
};
} // namespace torque

View File

@ -70,6 +70,15 @@ const Type* Declarations::LookupType(const QualifiedName& name) {
return LookupTypeAlias(name)->type();
}
const Type* Declarations::LookupType(const Identifier* name) {
const TypeAlias* alias = LookupTypeAlias(QualifiedName(name->value));
if (GlobalContext::collect_language_server_data()) {
LanguageServerData::AddDefinition(name->pos,
alias->GetDeclarationPosition());
}
return alias->type();
}
const Type* Declarations::LookupType(std::string name) {
return LookupType(QualifiedName(std::move(name)));
}
@ -80,36 +89,6 @@ const Type* Declarations::LookupGlobalType(const std::string& name) {
return declaration->type();
}
const Type* Declarations::GetType(TypeExpression* type_expression) {
if (auto* basic = BasicTypeExpression::DynamicCast(type_expression)) {
std::string name =
(basic->is_constexpr ? CONSTEXPR_TYPE_PREFIX : "") + basic->name;
const TypeAlias* alias =
LookupTypeAlias(QualifiedName{basic->namespace_qualification, name});
if (GlobalContext::collect_language_server_data()) {
LanguageServerData::AddDefinition(type_expression->pos,
alias->GetDeclarationPosition());
}
return alias->type();
} else if (auto* union_type =
UnionTypeExpression::DynamicCast(type_expression)) {
return TypeOracle::GetUnionType(GetType(union_type->a),
GetType(union_type->b));
} else if (auto* reference_type =
ReferenceTypeExpression::DynamicCast(type_expression)) {
return TypeOracle::GetReferenceType(
GetType(reference_type->referenced_type));
} else {
auto* function_type_exp = FunctionTypeExpression::cast(type_expression);
TypeVector argument_types;
for (TypeExpression* type_exp : function_type_exp->parameters) {
argument_types.push_back(GetType(type_exp));
}
return TypeOracle::GetBuiltinPointerType(
argument_types, GetType(function_type_exp->return_type));
}
}
Builtin* Declarations::FindSomeInternalBuiltinWithType(
const BuiltinPointerType* type) {
for (auto& declarable : GlobalContext::AllDeclarables()) {
@ -162,50 +141,19 @@ Namespace* Declarations::DeclareNamespace(const std::string& name) {
return Declare(name, std::unique_ptr<Namespace>(new Namespace(name)));
}
const AbstractType* Declarations::DeclareAbstractType(
const Identifier* name, bool transient, std::string generated,
base::Optional<const AbstractType*> non_constexpr_version,
const base::Optional<Identifier*>& parent) {
void Declarations::DeclareType(const Identifier* name, const Type* type) {
CheckAlreadyDeclared<TypeAlias>(name->value, "type");
const Type* parent_type = nullptr;
if (parent) {
auto parent_type_alias = LookupTypeAlias(QualifiedName{(*parent)->value});
parent_type = parent_type_alias->type();
if (GlobalContext::collect_language_server_data()) {
LanguageServerData::AddDefinition(
(*parent)->pos, parent_type_alias->GetDeclarationPosition());
}
}
if (generated == "" && parent) {
generated = parent_type->GetGeneratedTNodeTypeName();
}
const AbstractType* type = TypeOracle::GetAbstractType(
parent_type, name->value, transient, generated, non_constexpr_version);
DeclareType(name, type, false);
return type;
Declare(name->value,
std::unique_ptr<TypeAlias>(new TypeAlias(type, true, name->pos)));
}
void Declarations::DeclareType(const Identifier* name, const Type* type,
bool redeclaration) {
const TypeAlias* Declarations::PredeclareTypeAlias(const Identifier* name,
TypeDeclaration* type,
bool redeclaration) {
CheckAlreadyDeclared<TypeAlias>(name->value, "type");
Declare(name->value, std::unique_ptr<TypeAlias>(
new TypeAlias(type, redeclaration, name->pos)));
}
StructType* Declarations::DeclareStruct(const Identifier* name) {
StructType* new_type = TypeOracle::GetStructType(name->value);
DeclareType(name, new_type, false);
return new_type;
}
ClassType* Declarations::DeclareClass(const Type* super_type,
const Identifier* name, bool is_extern,
bool generate_print, bool transient,
const std::string& generates) {
ClassType* new_type = TypeOracle::GetClassType(
super_type, name->value, is_extern, generate_print, transient, generates);
DeclareType(name, new_type, false);
return new_type;
std::unique_ptr<TypeAlias> alias_ptr(
new TypeAlias(type, redeclaration, name->pos));
return Declare(name->value, std::move(alias_ptr));
}
Macro* Declarations::CreateMacro(

View File

@ -56,9 +56,9 @@ class Declarations {
static const TypeAlias* LookupTypeAlias(const QualifiedName& name);
static const Type* LookupType(const QualifiedName& name);
static const Type* LookupType(const Identifier* identifier);
static const Type* LookupType(std::string name);
static const Type* LookupGlobalType(const std::string& name);
static const Type* GetType(TypeExpression* type_expression);
static Builtin* FindSomeInternalBuiltinWithType(
const BuiltinPointerType* type);
@ -73,21 +73,11 @@ class Declarations {
static Generic* LookupUniqueGeneric(const QualifiedName& name);
static Namespace* DeclareNamespace(const std::string& name);
static void DeclareType(const Identifier* name, const Type* type);
static const AbstractType* DeclareAbstractType(
const Identifier* name, bool transient, std::string generated,
base::Optional<const AbstractType*> non_constexpr_version,
const base::Optional<Identifier*>& parent = {});
static void DeclareType(const Identifier* name, const Type* type,
bool redeclaration);
static StructType* DeclareStruct(const Identifier* name);
static ClassType* DeclareClass(const Type* super, const Identifier* name,
bool is_extern, bool generate_print,
bool transient, const std::string& generates);
static const TypeAlias* PredeclareTypeAlias(const Identifier* name,
TypeDeclaration* type,
bool redeclaration);
static Macro* CreateMacro(std::string external_name,
std::string readable_name,
base::Optional<std::string> external_assembler_name,

View File

@ -64,6 +64,7 @@ enum class ParseResultHolderBase::TypeId {
kOptionalStdString,
kStdVectorOfStatementPtr,
kStdVectorOfDeclarationPtr,
kStdVectorOfStdVectorOfDeclarationPtr,
kStdVectorOfExpressionPtr,
kExpressionWithSource,
kParameterList,
@ -189,6 +190,15 @@ inline base::Optional<ParseResult> DefaultAction(
return child_results->Next();
}
template <class T, Action action>
inline Action AsSingletonVector() {
return [](ParseResultIterator* child_results) -> base::Optional<ParseResult> {
auto result = action(child_results);
if (!result) return result;
return ParseResult{std::vector<T>{(*result).Cast<T>()}};
};
}
// A rule of the context-free grammar. Each rule can have an action attached to
// it, which is executed after the parsing is finished.
class Rule final {

View File

@ -1,34 +0,0 @@
// Copyright 2017 the V8 project authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#include "src/torque/file-visitor.h"
#include "src/torque/declarable.h"
namespace v8 {
namespace internal {
namespace torque {
Signature FileVisitor::MakeSignature(const CallableNodeSignature* signature) {
LabelDeclarationVector definition_vector;
for (const auto& label : signature->labels) {
LabelDeclaration def = {label.name, GetTypeVector(label.types)};
definition_vector.push_back(def);
}
base::Optional<std::string> arguments_variable;
if (signature->parameters.has_varargs)
arguments_variable = signature->parameters.arguments_variable;
Signature result{signature->parameters.names,
arguments_variable,
{GetTypeVector(signature->parameters.types),
signature->parameters.has_varargs},
signature->parameters.implicit_count,
Declarations::GetType(signature->return_type),
definition_vector};
return result;
}
} // namespace torque
} // namespace internal
} // namespace v8

View File

@ -1,38 +0,0 @@
// Copyright 2017 the V8 project authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#ifndef V8_TORQUE_FILE_VISITOR_H_
#define V8_TORQUE_FILE_VISITOR_H_
#include <deque>
#include <string>
#include "src/torque/ast.h"
#include "src/torque/global-context.h"
#include "src/torque/types.h"
#include "src/torque/utils.h"
namespace v8 {
namespace internal {
namespace torque {
class FileVisitor {
public:
TypeVector GetTypeVector(const std::vector<TypeExpression*>& v) {
TypeVector result;
for (TypeExpression* t : v) {
result.push_back(Declarations::GetType(t));
}
return result;
}
protected:
Signature MakeSignature(const CallableNodeSignature* signature);
};
} // namespace torque
} // namespace internal
} // namespace v8
#endif // V8_TORQUE_FILE_VISITOR_H_

View File

@ -10,6 +10,7 @@
#include "src/torque/implementation-visitor.h"
#include "src/torque/parameter-difference.h"
#include "src/torque/server-data.h"
#include "src/torque/type-visitor.h"
namespace v8 {
namespace internal {
@ -557,7 +558,7 @@ const Type* ImplementationVisitor::Visit(
base::Optional<const Type*> type;
if (stmt->type) {
type = Declarations::GetType(*stmt->type);
type = TypeVisitor::ComputeType(*stmt->type);
if ((*type)->IsConstexpr() && !stmt->const_qualified) {
ReportError(
"cannot declare variable with constexpr type. Use 'const' instead.");
@ -774,8 +775,8 @@ VisitResult ImplementationVisitor::Visit(NumberLiteralExpression* expr) {
VisitResult ImplementationVisitor::Visit(AssumeTypeImpossibleExpression* expr) {
VisitResult result = Visit(expr->expression);
const Type* result_type =
SubtractType(result.type(), Declarations::GetType(expr->excluded_type));
const Type* result_type = SubtractType(
result.type(), TypeVisitor::ComputeType(expr->excluded_type));
if (result_type->IsNever()) {
ReportError("unreachable code");
}
@ -1128,7 +1129,7 @@ const Type* ImplementationVisitor::Visit(ForOfLoopStatement* stmt) {
VisitResult result = GenerateCall("[]", {{expression_result, index}, {}});
if (stmt->var_declaration->type) {
const Type* declared_type =
Declarations::GetType(*stmt->var_declaration->type);
TypeVisitor::ComputeType(*stmt->var_declaration->type);
result = GenerateImplicitConvert(declared_type, result);
}
element_result = element_scope.Yield(result);
@ -1196,7 +1197,7 @@ VisitResult ImplementationVisitor::Visit(TryLabelExpression* expr) {
TypeVector parameter_types;
for (size_t i = 0; i < parameter_count; ++i) {
const Type* type =
Declarations::GetType(expr->label_block->parameters.types[i]);
TypeVisitor::ComputeType(expr->label_block->parameters.types[i]);
parameter_types.push_back(type);
if (type->IsConstexpr()) {
ReportError("no constexpr type allowed for label arguments");
@ -1443,7 +1444,7 @@ VisitResult ImplementationVisitor::AddVariableObjectSize(
VisitResult ImplementationVisitor::Visit(NewExpression* expr) {
StackScope stack_scope(this);
const Type* type = Declarations::GetType(expr->type);
const Type* type = TypeVisitor::ComputeType(expr->type);
const ClassType* class_type = ClassType::DynamicCast(type);
if (class_type == nullptr) {
ReportError("type for new expression must be a class, \"", *type,
@ -1675,7 +1676,7 @@ Callable* GetOrCreateSpecialization(const SpecializationKey& key) {
key.generic->GetSpecialization(key.specialized_types)) {
return *specialization;
}
return DeclarationVisitor().SpecializeImplicit(key);
return DeclarationVisitor::SpecializeImplicit(key);
}
} // namespace
@ -1734,7 +1735,7 @@ Callable* ImplementationVisitor::LookupCallable(
if (!inferred_specialization_types) continue;
overloads.push_back(generic);
overload_signatures.push_back(
DeclarationVisitor().MakeSpecializedSignature(
DeclarationVisitor::MakeSpecializedSignature(
SpecializationKey{generic, *inferred_specialization_types}));
} else if (Callable* callable = Callable::DynamicCast(declarable)) {
overloads.push_back(callable);
@ -1815,14 +1816,14 @@ Callable* ImplementationVisitor::LookupCallable(
const QualifiedName& name, const Container& declaration_container,
const Arguments& arguments, const TypeVector& specialization_types) {
return LookupCallable(name, declaration_container,
arguments.parameters.GetTypeVector(), arguments.labels,
specialization_types);
arguments.parameters.ComputeTypeVector(),
arguments.labels, specialization_types);
}
Method* ImplementationVisitor::LookupMethod(
const std::string& name, LocationReference this_reference,
const Arguments& arguments, const TypeVector& specialization_types) {
TypeVector types(arguments.parameters.GetTypeVector());
TypeVector types(arguments.parameters.ComputeTypeVector());
types.insert(types.begin(), this_reference.ReferencedType());
return Method::cast(LookupCallable(
{{}, name},
@ -1854,7 +1855,7 @@ VisitResult ImplementationVisitor::GenerateCopy(const VisitResult& to_copy) {
VisitResult ImplementationVisitor::Visit(StructExpression* expr) {
StackScope stack_scope(this);
const Type* raw_type = Declarations::GetType(expr->type);
const Type* raw_type = TypeVisitor::ComputeType(expr->type);
if (!raw_type->IsStructType()) {
ReportError(*raw_type, " is not a struct but used like one");
}
@ -1998,8 +1999,8 @@ LocationReference ImplementationVisitor::GetLocationReference(
}
if (expr->generic_arguments.size() != 0) {
Generic* generic = Declarations::LookupUniqueGeneric(name);
Callable* specialization = GetOrCreateSpecialization(
SpecializationKey{generic, GetTypeVector(expr->generic_arguments)});
Callable* specialization = GetOrCreateSpecialization(SpecializationKey{
generic, TypeVisitor::ComputeTypeVector(expr->generic_arguments)});
if (Builtin* builtin = Builtin::DynamicCast(specialization)) {
DCHECK(!builtin->IsExternal());
return LocationReference::Temporary(GetBuiltinCode(builtin),
@ -2095,7 +2096,7 @@ void ImplementationVisitor::GenerateAssignToLocation(
VisitResult ImplementationVisitor::GeneratePointerCall(
Expression* callee, const Arguments& arguments, bool is_tailcall) {
StackScope scope(this);
TypeVector parameter_types(arguments.parameters.GetTypeVector());
TypeVector parameter_types(arguments.parameters.ComputeTypeVector());
VisitResult callee_result = Visit(callee);
if (!callee_result.type()->IsBuiltinPointerType()) {
std::stringstream stream;
@ -2433,7 +2434,7 @@ VisitResult ImplementationVisitor::Visit(CallExpression* expr,
QualifiedName name = QualifiedName(expr->callee->namespace_qualification,
expr->callee->name->value);
TypeVector specialization_types =
GetTypeVector(expr->callee->generic_arguments);
TypeVisitor::ComputeTypeVector(expr->callee->generic_arguments);
bool has_template_arguments = !specialization_types.empty();
for (Expression* arg : expr->arguments)
arguments.parameters.push_back(Visit(arg));
@ -2459,7 +2460,7 @@ VisitResult ImplementationVisitor::Visit(CallMethodExpression* expr) {
Arguments arguments;
std::string method_name = expr->method->name->value;
TypeVector specialization_types =
GetTypeVector(expr->method->generic_arguments);
TypeVisitor::ComputeTypeVector(expr->method->generic_arguments);
LocationReference target = GetLocationReference(expr->target);
if (!target.IsVariableAccess()) {
VisitResult result = GenerateFetchFromLocation(target);
@ -2474,7 +2475,7 @@ VisitResult ImplementationVisitor::Visit(CallMethodExpression* expr) {
arguments.parameters.push_back(Visit(arg));
}
arguments.labels = LabelsFromIdentifiers(expr->labels);
TypeVector argument_types = arguments.parameters.GetTypeVector();
TypeVector argument_types = arguments.parameters.ComputeTypeVector();
DCHECK_EQ(expr->method->namespace_qualification.size(), 0);
QualifiedName qualified_name = QualifiedName(method_name);
Callable* callable = nullptr;
@ -2485,7 +2486,8 @@ VisitResult ImplementationVisitor::Visit(CallMethodExpression* expr) {
VisitResult ImplementationVisitor::Visit(IntrinsicCallExpression* expr) {
StackScope scope(this);
Arguments arguments;
TypeVector specialization_types = GetTypeVector(expr->generic_arguments);
TypeVector specialization_types =
TypeVisitor::ComputeTypeVector(expr->generic_arguments);
for (Expression* arg : expr->arguments)
arguments.parameters.push_back(Visit(arg));
return scope.Yield(
@ -2675,7 +2677,6 @@ void ImplementationVisitor::GenerateCatchBlock(
}
}
}
void ImplementationVisitor::VisitAllDeclarables() {
CurrentCallable::Scope current_callable(nullptr);
const std::vector<std::unique_ptr<Declarable>>& all_declarables =

View File

@ -10,7 +10,6 @@
#include "src/base/macros.h"
#include "src/torque/ast.h"
#include "src/torque/cfg.h"
#include "src/torque/file-visitor.h"
#include "src/torque/global-context.h"
#include "src/torque/types.h"
#include "src/torque/utils.h"
@ -274,7 +273,7 @@ struct Arguments {
bool IsCompatibleSignature(const Signature& sig, const TypeVector& types,
size_t label_count);
class ImplementationVisitor : public FileVisitor {
class ImplementationVisitor {
public:
void GenerateBuiltinDefinitions(std::string& file_name);
void GenerateClassDefinitions(std::string& file_name);

View File

@ -244,21 +244,6 @@ void HandleTorqueFileListNotification(TorqueFileListNotification notification,
files.push_back(file_json.ToString());
Logger::Log(" ", file_json.ToString(), "\n");
}
// The Torque compiler expects to see some files first,
// we need to order them in the correct way.
// TODO(szuend): Remove this, once the compiler doesn't require the input
// files to be in a specific order.
std::vector<std::string> sort_to_front = {
"base.tq", "frames.tq", "arguments.tq", "array.tq", "typed_array.tq"};
std::sort(files.begin(), files.end(), [&](std::string a, std::string b) {
for (const std::string& fixed_file : sort_to_front) {
if (a.find(fixed_file) != std::string::npos) return true;
if (b.find(fixed_file) != std::string::npos) return false;
}
return a < b;
});
RecompileTorqueWithDiagnostics(writer);
}

View File

@ -53,10 +53,17 @@ void CompileCurrentAst(TorqueCompilerOptions options) {
}
TypeOracle::Scope type_oracle;
DeclarationVisitor declaration_visitor;
// Two-step process of predeclaration + resolution allows to resolve type
// declarations independent of the order they are given.
TypeDeclarationVisitor::Predeclare(GlobalContext::Get().ast());
TypeDeclarationVisitor::ResolvePredeclarations();
declaration_visitor.Visit(GlobalContext::Get().ast());
declaration_visitor.FinalizeStructsAndClasses();
// Process other declarations.
DeclarationVisitor::Visit(GlobalContext::Get().ast());
// A class types' fields are resolved here, which allows two class fields to
// mutually refer to each others.
TypeOracle::FinalizeClassTypes();
ImplementationVisitor implementation_visitor;
for (Namespace* n : GlobalContext::Get().GetNamespaces()) {

View File

@ -4,6 +4,7 @@
#include <cctype>
#include "src/torque/constants.h"
#include "src/torque/earley-parser.h"
#include "src/torque/torque-parser.h"
#include "src/torque/utils.h"
@ -119,6 +120,10 @@ V8_EXPORT_PRIVATE const ParseResultTypeId
ParseResultHolder<std::vector<Declaration*>>::id =
ParseResultTypeId::kStdVectorOfDeclarationPtr;
template <>
V8_EXPORT_PRIVATE const ParseResultTypeId
ParseResultHolder<std::vector<std::vector<Declaration*>>>::id =
ParseResultTypeId::kStdVectorOfStdVectorOfDeclarationPtr;
template <>
V8_EXPORT_PRIVATE const ParseResultTypeId
ParseResultHolder<std::vector<Expression*>>::id =
ParseResultTypeId::kStdVectorOfExpressionPtr;
@ -177,10 +182,12 @@ V8_EXPORT_PRIVATE const ParseResultTypeId
namespace {
base::Optional<ParseResult> AddGlobalDeclaration(
base::Optional<ParseResult> AddGlobalDeclarations(
ParseResultIterator* child_results) {
auto declaration = child_results->NextAs<Declaration*>();
CurrentAst::Get().declarations().push_back(declaration);
auto declarations = child_results->NextAs<std::vector<Declaration*>>();
for (Declaration* declaration : declarations) {
CurrentAst::Get().declarations().push_back(declaration);
}
return base::nullopt;
}
@ -193,6 +200,16 @@ void LintGenericParameters(const GenericParameters& parameters) {
}
}
base::Optional<ParseResult> ConcatList(ParseResultIterator* child_results) {
auto list_of_lists =
child_results->NextAs<std::vector<std::vector<Declaration*>>>();
std::vector<Declaration*> result;
for (auto& list : list_of_lists) {
result.insert(result.end(), list.begin(), list.end());
}
return ParseResult{result};
}
void CheckNotDeferredStatement(Statement* statement) {
CurrentSourcePosition::Scope source_position(statement->pos);
if (BlockStatement* block = BlockStatement::DynamicCast(statement)) {
@ -396,7 +413,7 @@ base::Optional<ParseResult> MakeDebugStatement(
base::Optional<ParseResult> MakeVoidType(ParseResultIterator* child_results) {
TypeExpression* result =
MakeNode<BasicTypeExpression>(std::vector<std::string>{}, false, "void");
MakeNode<BasicTypeExpression>(std::vector<std::string>{}, "void");
return ParseResult{result};
}
@ -531,7 +548,7 @@ base::Optional<ParseResult> MakeTypeAliasDeclaration(
return ParseResult{result};
}
base::Optional<ParseResult> MakeTypeDeclaration(
base::Optional<ParseResult> MakeAbstractTypeDeclaration(
ParseResultIterator* child_results) {
auto transient = child_results->NextAs<bool>();
auto name = child_results->NextAs<Identifier*>();
@ -540,11 +557,31 @@ base::Optional<ParseResult> MakeTypeDeclaration(
}
auto extends = child_results->NextAs<base::Optional<Identifier*>>();
auto generates = child_results->NextAs<base::Optional<std::string>>();
Declaration* decl = MakeNode<AbstractTypeDeclaration>(
name, transient, extends, std::move(generates));
auto constexpr_generates =
child_results->NextAs<base::Optional<std::string>>();
Declaration* result =
MakeNode<TypeDeclaration>(name, transient, extends, std::move(generates),
std::move(constexpr_generates));
std::vector<Declaration*> result{decl};
if (constexpr_generates) {
// Create a AbstractTypeDeclaration for the associated constexpr type.
Identifier* constexpr_name =
MakeNode<Identifier>(CONSTEXPR_TYPE_PREFIX + name->value);
constexpr_name->pos = name->pos;
base::Optional<Identifier*> constexpr_extends;
if (extends) {
constexpr_extends =
MakeNode<Identifier>(CONSTEXPR_TYPE_PREFIX + (*extends)->value);
(*constexpr_extends)->pos = name->pos;
}
AbstractTypeDeclaration* constexpr_decl = MakeNode<AbstractTypeDeclaration>(
constexpr_name, transient, constexpr_extends, constexpr_generates);
constexpr_decl->pos = name->pos;
result.push_back(constexpr_decl);
}
return ParseResult{result};
}
@ -684,7 +721,8 @@ base::Optional<ParseResult> MakeBasicTypeExpression(
auto is_constexpr = child_results->NextAs<bool>();
auto name = child_results->NextAs<std::string>();
TypeExpression* result = MakeNode<BasicTypeExpression>(
std::move(namespace_qualification), is_constexpr, std::move(name));
std::move(namespace_qualification),
is_constexpr ? GetConstexprName(name) : std::move(name));
return ParseResult{result};
}
@ -974,8 +1012,8 @@ base::Optional<ParseResult> MakeCatchBlock(ParseResultIterator* child_results) {
}
ParameterList parameters;
parameters.names.push_back(MakeNode<Identifier>(variable));
parameters.types.push_back(MakeNode<BasicTypeExpression>(
std::vector<std::string>{}, false, "Object"));
parameters.types.push_back(
MakeNode<BasicTypeExpression>(std::vector<std::string>{}, "Object"));
parameters.has_varargs = false;
LabelBlock* result = MakeNode<LabelBlock>(MakeNode<Identifier>("_catch"),
std::move(parameters), body);
@ -1650,14 +1688,14 @@ struct TorqueGrammar : Grammar {
optionalLabelList, &block},
MakeMethodDeclaration)};
// Result: Declaration*
// Result: std::vector<Declaration*>
Symbol declaration = {
Rule({Token("const"), &name, Token(":"), &type, Token("="), expression,
Token(";")},
MakeConstDeclaration),
AsSingletonVector<Declaration*, MakeConstDeclaration>()),
Rule({Token("const"), &name, Token(":"), &type, Token("generates"),
&externalString, Token(";")},
MakeExternConstDeclaration),
AsSingletonVector<Declaration*, MakeExternConstDeclaration>()),
Rule({CheckIf(Token("@generatePrint")), CheckIf(Token("extern")),
CheckIf(Token("transient")), Token("class"), &name,
Optional<TypeExpression*>(Sequence({Token("extends"), &type})),
@ -1665,10 +1703,10 @@ struct TorqueGrammar : Grammar {
Sequence({Token("generates"), &externalString})),
Token("{"), List<Declaration*>(&method),
List<ClassFieldExpression>(&classField), Token("}")},
MakeClassDeclaration),
AsSingletonVector<Declaration*, MakeClassDeclaration>()),
Rule({Token("struct"), &name, Token("{"), List<Declaration*>(&method),
List<StructFieldExpression>(&structField), Token("}")},
MakeStructDeclaration),
AsSingletonVector<Declaration*, MakeStructDeclaration>()),
Rule({CheckIf(Token("transient")), Token("type"), &name,
Optional<Identifier*>(Sequence({Token("extends"), &name})),
Optional<std::string>(
@ -1676,13 +1714,13 @@ struct TorqueGrammar : Grammar {
Optional<std::string>(
Sequence({Token("constexpr"), &externalString})),
Token(";")},
MakeTypeDeclaration),
MakeAbstractTypeDeclaration),
Rule({Token("type"), &name, Token("="), &type, Token(";")},
MakeTypeAliasDeclaration),
AsSingletonVector<Declaration*, MakeTypeAliasDeclaration>()),
Rule({Token("intrinsic"), &intrinsicName,
TryOrDefault<GenericParameters>(&genericParameters),
&parameterListNoVararg, &optionalReturnType, Token(";")},
MakeIntrinsicDeclaration),
AsSingletonVector<Declaration*, MakeIntrinsicDeclaration>()),
Rule({Token("extern"), CheckIf(Token("transitioning")),
Optional<std::string>(
Sequence({Token("operator"), &externalString})),
@ -1691,16 +1729,16 @@ struct TorqueGrammar : Grammar {
&identifier, TryOrDefault<GenericParameters>(&genericParameters),
&typeListMaybeVarArgs, &optionalReturnType, optionalLabelList,
Token(";")},
MakeExternalMacro),
AsSingletonVector<Declaration*, MakeExternalMacro>()),
Rule({Token("extern"), CheckIf(Token("transitioning")),
CheckIf(Token("javascript")), Token("builtin"), &identifier,
TryOrDefault<GenericParameters>(&genericParameters),
&typeListMaybeVarArgs, &optionalReturnType, Token(";")},
MakeExternalBuiltin),
AsSingletonVector<Declaration*, MakeExternalBuiltin>()),
Rule(
{Token("extern"), CheckIf(Token("transitioning")), Token("runtime"),
&identifier, &typeListMaybeVarArgs, &optionalReturnType, Token(";")},
MakeExternalRuntime),
AsSingletonVector<Declaration*, MakeExternalRuntime>()),
Rule({CheckIf(Token("transitioning")),
Optional<std::string>(
Sequence({Token("operator"), &externalString})),
@ -1708,26 +1746,31 @@ struct TorqueGrammar : Grammar {
TryOrDefault<GenericParameters>(&genericParameters),
&parameterListNoVararg, &optionalReturnType, optionalLabelList,
&optionalBody},
MakeTorqueMacroDeclaration),
AsSingletonVector<Declaration*, MakeTorqueMacroDeclaration>()),
Rule({CheckIf(Token("transitioning")), CheckIf(Token("javascript")),
Token("builtin"), &identifier,
TryOrDefault<GenericParameters>(&genericParameters),
&parameterListAllowVararg, &optionalReturnType, &optionalBody},
MakeTorqueBuiltinDeclaration),
AsSingletonVector<Declaration*, MakeTorqueBuiltinDeclaration>()),
Rule({&identifier, &genericSpecializationTypeList,
&parameterListAllowVararg, &optionalReturnType, optionalLabelList,
&block},
MakeSpecializationDeclaration),
Rule({Token("#include"), &externalString}, MakeCppIncludeDeclaration)};
AsSingletonVector<Declaration*, MakeSpecializationDeclaration>()),
Rule({Token("#include"), &externalString},
AsSingletonVector<Declaration*, MakeCppIncludeDeclaration>())};
// Result: Declaration*
// Result: std::vector<Declaration*>
Symbol declarationList = {
Rule({List<std::vector<Declaration*>>(&declaration)}, ConcatList)};
// Result: std::vector<Declaration*>
Symbol namespaceDeclaration = {
Rule({Token("namespace"), &identifier, Token("{"),
List<Declaration*>(&declaration), Token("}")},
MakeNamespaceDeclaration)};
Rule({Token("namespace"), &identifier, Token("{"), &declarationList,
Token("}")},
AsSingletonVector<Declaration*, MakeNamespaceDeclaration>())};
Symbol file = {Rule({&file, &namespaceDeclaration}, AddGlobalDeclaration),
Rule({&file, &declaration}, AddGlobalDeclaration), Rule({})};
Symbol file = {Rule({&file, &namespaceDeclaration}, AddGlobalDeclarations),
Rule({&file, &declaration}, AddGlobalDeclarations), Rule({})};
};
} // namespace

View File

@ -10,6 +10,12 @@ namespace torque {
DEFINE_CONTEXTUAL_VARIABLE(TypeOracle)
void TypeOracle::FinalizeClassTypes() {
for (const std::unique_ptr<AggregateType>& p : Get().struct_types_) {
p->Finalize();
}
}
} // namespace torque
} // namespace internal
} // namespace v8

View File

@ -19,8 +19,7 @@ class TypeOracle : public ContextualClass<TypeOracle> {
public:
static const AbstractType* GetAbstractType(
const Type* parent, std::string name, bool transient,
std::string generated,
base::Optional<const AbstractType*> non_constexpr_version) {
std::string generated, const Type* non_constexpr_version) {
AbstractType* result =
new AbstractType(parent, transient, std::move(name),
std::move(generated), non_constexpr_version);
@ -36,10 +35,12 @@ class TypeOracle : public ContextualClass<TypeOracle> {
static ClassType* GetClassType(const Type* parent, const std::string& name,
bool is_extern, bool generate_print,
bool transient, const std::string& generates) {
bool transient, const std::string& generates,
ClassDeclaration* decl,
const TypeAlias* alias) {
ClassType* result =
new ClassType(parent, CurrentNamespace(), name, is_extern,
generate_print, transient, generates);
generate_print, transient, generates, decl, alias);
Get().struct_types_.push_back(std::unique_ptr<ClassType>(result));
return result;
}
@ -207,6 +208,8 @@ class TypeOracle : public ContextualClass<TypeOracle> {
return false;
}
static void FinalizeClassTypes();
private:
const Type* GetBuiltinType(const std::string& name) {
return Declarations::LookupGlobalType(name);
@ -217,7 +220,7 @@ class TypeOracle : public ContextualClass<TypeOracle> {
Deduplicator<UnionType> union_types_;
Deduplicator<ReferenceType> reference_types_;
std::vector<std::unique_ptr<Type>> nominal_types_;
std::vector<std::unique_ptr<Type>> struct_types_;
std::vector<std::unique_ptr<AggregateType>> struct_types_;
std::vector<std::unique_ptr<Type>> top_types_;
};

289
src/torque/type-visitor.cc Normal file
View File

@ -0,0 +1,289 @@
// Copyright 2017 the V8 project authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#include "src/torque/type-visitor.h"
#include "src/globals.h"
#include "src/torque/declarable.h"
#include "src/torque/global-context.h"
#include "src/torque/server-data.h"
#include "src/torque/type-oracle.h"
namespace v8 {
namespace internal {
namespace torque {
const Type* TypeVisitor::ComputeType(TypeDeclaration* decl) {
CurrentSourcePosition::Scope scope(decl->pos);
switch (decl->kind) {
#define ENUM_ITEM(name) \
case AstNode::Kind::k##name: \
return ComputeType(name::cast(decl));
AST_TYPE_DECLARATION_NODE_KIND_LIST(ENUM_ITEM)
#undef ENUM_ITEM
default:
UNIMPLEMENTED();
}
}
const Type* TypeVisitor::ComputeType(TypeAliasDeclaration* decl) {
const Type* type = ComputeType(decl->type);
type->AddAlias(decl->name->value);
return type;
}
namespace {
std::string ComputeGeneratesType(base::Optional<std::string> opt_gen,
bool enforce_tnode_type) {
if (!opt_gen) return "";
const std::string& generates = *opt_gen;
if (enforce_tnode_type) {
if (generates.length() < 7 || generates.substr(0, 6) != "TNode<" ||
generates.substr(generates.length() - 1, 1) != ">") {
ReportError("generated type \"", generates,
"\" should be of the form \"TNode<...>\"");
}
return generates.substr(6, generates.length() - 7);
}
return generates;
}
} // namespace
const AbstractType* TypeVisitor::ComputeType(AbstractTypeDeclaration* decl) {
std::string generates =
ComputeGeneratesType(decl->generates, !decl->is_constexpr);
const Type* parent_type = nullptr;
if (decl->extends) {
parent_type = Declarations::LookupType(*decl->extends);
}
if (generates == "" && parent_type) {
generates = parent_type->GetGeneratedTNodeTypeName();
}
if (decl->is_constexpr && decl->transient) {
ReportError("cannot declare a transient type that is also constexpr");
}
const Type* non_constexpr_version = nullptr;
if (decl->is_constexpr) {
non_constexpr_version = Declarations::LookupType(
QualifiedName{GetNonConstexprName(decl->name->value)});
DCHECK_NOT_NULL(non_constexpr_version);
}
return TypeOracle::GetAbstractType(parent_type, decl->name->value,
decl->transient, generates,
non_constexpr_version);
}
void DeclareMethods(AggregateType* container_type,
const std::vector<Declaration*>& methods) {
for (auto declaration : methods) {
CurrentSourcePosition::Scope pos_scope(declaration->pos);
StandardDeclaration* standard_declaration =
StandardDeclaration::DynamicCast(declaration);
DCHECK(standard_declaration);
TorqueMacroDeclaration* method =
TorqueMacroDeclaration::DynamicCast(standard_declaration->callable);
Signature signature = TypeVisitor::MakeSignature(method->signature.get());
signature.parameter_names.insert(
signature.parameter_names.begin() + signature.implicit_count,
MakeNode<Identifier>(kThisParameterName));
Statement* body = *(standard_declaration->body);
std::string method_name(method->name);
signature.parameter_types.types.insert(
signature.parameter_types.types.begin() + signature.implicit_count,
container_type);
Declarations::CreateMethod(container_type, method_name, signature, false,
body);
}
}
const StructType* TypeVisitor::ComputeType(StructDeclaration* decl) {
CurrentSourcePosition::Scope position_activator(decl->pos);
StructType* struct_type = TypeOracle::GetStructType(decl->name->value);
size_t offset = 0;
for (auto& field : decl->fields) {
CurrentSourcePosition::Scope position_activator(
field.name_and_type.type->pos);
const Type* field_type = TypeVisitor::ComputeType(field.name_and_type.type);
struct_type->RegisterField({field.name_and_type.name->pos,
struct_type,
base::nullopt,
{field.name_and_type.name->value, field_type},
offset,
false,
field.const_qualified});
offset += LoweredSlotCount(field_type);
}
DeclareMethods(struct_type, decl->methods);
return struct_type;
}
const ClassType* TypeVisitor::ComputeType(ClassDeclaration* decl) {
ClassType* new_class;
// TODO(sigurds): Remove this hack by introducing a declarable for classes.
const TypeAlias* alias =
Declarations::LookupTypeAlias(QualifiedName(decl->name->value));
DCHECK_EQ(*alias->delayed_, decl);
if (decl->is_extern) {
if (!decl->super) {
ReportError("Extern class must extend another type.");
}
const Type* super_type = TypeVisitor::ComputeType(*decl->super);
if (super_type != TypeOracle::GetTaggedType()) {
const ClassType* super_class = ClassType::DynamicCast(super_type);
if (!super_class) {
ReportError(
"class \"", decl->name->value,
"\" must extend either Tagged or an already declared class");
}
}
std::string generates = decl->name->value;
if (decl->generates) {
bool enforce_tnode_type = true;
generates = ComputeGeneratesType(decl->generates, enforce_tnode_type);
}
new_class = TypeOracle::GetClassType(
super_type, decl->name->value, decl->is_extern, decl->generate_print,
decl->transient, generates, decl, alias);
} else {
if (decl->super) {
ReportError("Only extern classes can inherit.");
}
if (decl->generates) {
ReportError("Only extern classes can specify a generated type.");
}
new_class = TypeOracle::GetClassType(
TypeOracle::GetTaggedType(), decl->name->value, decl->is_extern,
decl->generate_print, decl->transient, "FixedArray", decl, alias);
}
GlobalContext::RegisterClass(decl->name->value, new_class);
return new_class;
}
const Type* TypeVisitor::ComputeType(TypeExpression* type_expression) {
if (auto* basic = BasicTypeExpression::DynamicCast(type_expression)) {
const TypeAlias* alias = Declarations::LookupTypeAlias(
QualifiedName{basic->namespace_qualification, basic->name});
if (GlobalContext::collect_language_server_data()) {
LanguageServerData::AddDefinition(type_expression->pos,
alias->GetDeclarationPosition());
}
return alias->type();
} else if (auto* union_type =
UnionTypeExpression::DynamicCast(type_expression)) {
return TypeOracle::GetUnionType(ComputeType(union_type->a),
ComputeType(union_type->b));
} else if (auto* reference_type =
ReferenceTypeExpression::DynamicCast(type_expression)) {
return TypeOracle::GetReferenceType(
ComputeType(reference_type->referenced_type));
} else {
auto* function_type_exp = FunctionTypeExpression::cast(type_expression);
TypeVector argument_types;
for (TypeExpression* type_exp : function_type_exp->parameters) {
argument_types.push_back(ComputeType(type_exp));
}
return TypeOracle::GetBuiltinPointerType(
argument_types, ComputeType(function_type_exp->return_type));
}
}
Signature TypeVisitor::MakeSignature(const CallableNodeSignature* signature) {
LabelDeclarationVector definition_vector;
for (const auto& label : signature->labels) {
LabelDeclaration def = {label.name, ComputeTypeVector(label.types)};
definition_vector.push_back(def);
}
base::Optional<std::string> arguments_variable;
if (signature->parameters.has_varargs)
arguments_variable = signature->parameters.arguments_variable;
Signature result{signature->parameters.names,
arguments_variable,
{ComputeTypeVector(signature->parameters.types),
signature->parameters.has_varargs},
signature->parameters.implicit_count,
ComputeType(signature->return_type),
definition_vector};
return result;
}
void TypeVisitor::VisitClassFieldsAndMethods(
ClassType* class_type, const ClassDeclaration* class_declaration) {
const ClassType* super_class = class_type->GetSuperClass();
size_t class_offset = super_class ? super_class->size() : 0;
bool seen_indexed_field = false;
for (const ClassFieldExpression& field_expression :
class_declaration->fields) {
CurrentSourcePosition::Scope position_activator(
field_expression.name_and_type.type->pos);
const Type* field_type = ComputeType(field_expression.name_and_type.type);
if (!class_declaration->is_extern) {
if (!field_type->IsSubtypeOf(TypeOracle::GetTaggedType())) {
ReportError("non-extern classes do not support untagged fields");
}
if (field_expression.weak) {
ReportError("non-extern classes do not support weak fields");
}
}
if (field_expression.index) {
if (seen_indexed_field ||
(super_class && super_class->HasIndexedField())) {
ReportError(
"only one indexable field is currently supported per class");
}
seen_indexed_field = true;
const Field* index_field =
&(class_type->LookupFieldInternal(*field_expression.index));
class_type->RegisterField(
{field_expression.name_and_type.name->pos,
class_type,
index_field,
{field_expression.name_and_type.name->value, field_type},
class_offset,
field_expression.weak,
field_expression.const_qualified});
} else {
if (seen_indexed_field) {
ReportError("cannot declare non-indexable field \"",
field_expression.name_and_type.name,
"\" after an indexable field "
"declaration");
}
const Field& field = class_type->RegisterField(
{field_expression.name_and_type.name->pos,
class_type,
base::nullopt,
{field_expression.name_and_type.name->value, field_type},
class_offset,
field_expression.weak,
field_expression.const_qualified});
size_t field_size;
std::string size_string;
std::string machine_type;
std::tie(field_size, size_string, machine_type) =
field.GetFieldSizeInformation();
// Our allocations don't support alignments beyond kTaggedSize.
size_t alignment = std::min(size_t{kTaggedSize}, field_size);
if (class_offset % alignment != 0) {
ReportError("field ", field_expression.name_and_type.name,
" at offset ", class_offset, " is not ", alignment,
"-byte aligned.");
}
class_offset += field_size;
}
}
class_type->SetSize(class_offset);
class_type->GenerateAccessors();
DeclareMethods(class_type, class_declaration->methods);
}
} // namespace torque
} // namespace internal
} // namespace v8

45
src/torque/type-visitor.h Normal file
View File

@ -0,0 +1,45 @@
// Copyright 2017 the V8 project authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#ifndef V8_TORQUE_TYPE_VISITOR_H_
#define V8_TORQUE_TYPE_VISITOR_H_
#include <string>
#include "src/torque/ast.h"
#include "src/torque/types.h"
namespace v8 {
namespace internal {
namespace torque {
class TypeVisitor {
public:
static TypeVector ComputeTypeVector(const std::vector<TypeExpression*>& v) {
TypeVector result;
for (TypeExpression* t : v) {
result.push_back(ComputeType(t));
}
return result;
}
static const Type* ComputeType(TypeExpression* type_expression);
static void VisitClassFieldsAndMethods(
ClassType* class_type, const ClassDeclaration* class_declaration);
static Signature MakeSignature(const CallableNodeSignature* signature);
private:
friend class TypeAlias;
static const Type* ComputeType(TypeDeclaration* decl);
static const AbstractType* ComputeType(AbstractTypeDeclaration* decl);
static const Type* ComputeType(TypeAliasDeclaration* decl);
static const StructType* ComputeType(StructDeclaration* decl);
static const ClassType* ComputeType(ClassDeclaration* decl);
};
} // namespace torque
} // namespace internal
} // namespace v8
#endif // V8_TORQUE_TYPE_VISITOR_H_

View File

@ -5,8 +5,10 @@
#include <iostream>
#include "src/globals.h"
#include "src/torque/ast.h"
#include "src/torque/declarable.h"
#include "src/torque/type-oracle.h"
#include "src/torque/type-visitor.h"
#include "src/torque/types.h"
namespace v8 {
@ -195,7 +197,7 @@ const Type* SubtractType(const Type* a, const Type* b) {
return TypeOracle::GetUnionType(result);
}
void AggregateType::CheckForDuplicateFields() {
void AggregateType::CheckForDuplicateFields() const {
// Check the aggregate hierarchy and currently defined class for duplicate
// field declarations.
auto hierarchy = GetHierarchy();
@ -224,7 +226,8 @@ void AggregateType::CheckForDuplicateFields() {
}
}
std::vector<const AggregateType*> AggregateType::GetHierarchy() {
std::vector<const AggregateType*> AggregateType::GetHierarchy() const {
if (!is_finalized_) Finalize();
std::vector<const AggregateType*> hierarchy;
const AggregateType* current_container_type = this;
while (current_container_type != nullptr) {
@ -239,6 +242,7 @@ std::vector<const AggregateType*> AggregateType::GetHierarchy() {
}
bool AggregateType::HasField(const std::string& name) const {
if (!is_finalized_) Finalize();
for (auto& field : fields_) {
if (field.name_and_type.name == name) return true;
}
@ -250,7 +254,7 @@ bool AggregateType::HasField(const std::string& name) const {
return false;
}
const Field& AggregateType::LookupField(const std::string& name) const {
const Field& AggregateType::LookupFieldInternal(const std::string& name) const {
for (auto& field : fields_) {
if (field.name_and_type.name == name) return field;
}
@ -262,11 +266,17 @@ const Field& AggregateType::LookupField(const std::string& name) const {
ReportError("no field ", name, " found");
}
const Field& AggregateType::LookupField(const std::string& name) const {
if (!is_finalized_) Finalize();
return LookupFieldInternal(name);
}
std::string StructType::GetGeneratedTypeNameImpl() const {
return nspace()->ExternalName() + "::" + name();
}
std::vector<Method*> AggregateType::Methods(const std::string& name) const {
if (!is_finalized_) Finalize();
std::vector<Method*> result;
std::copy_if(methods_.begin(), methods_.end(), std::back_inserter(result),
[name](Macro* macro) { return macro->ReadableName() == name; });
@ -284,29 +294,21 @@ std::string StructType::ToExplicitString() const {
ClassType::ClassType(const Type* parent, Namespace* nspace,
const std::string& name, bool is_extern,
bool generate_print, bool transient,
const std::string& generates)
const std::string& generates, const ClassDeclaration* decl,
const TypeAlias* alias)
: AggregateType(Kind::kClassType, parent, nspace, name),
is_extern_(is_extern),
generate_print_(generate_print),
transient_(transient),
size_(0),
has_indexed_field_(false),
generates_(generates) {
CheckForDuplicateFields();
if (parent) {
if (const ClassType* super_class = ClassType::DynamicCast(parent)) {
if (super_class->HasIndexedField()) {
has_indexed_field_ = true;
}
}
}
}
generates_(generates),
decl_(decl),
alias_(alias) {}
bool ClassType::HasIndexedField() const {
if (has_indexed_field_) return true;
const ClassType* super_class = GetSuperClass();
if (super_class) return super_class->HasIndexedField();
return false;
if (!is_finalized_) Finalize();
return has_indexed_field_;
}
std::string ClassType::GetGeneratedTNodeTypeNameImpl() const {
@ -334,6 +336,67 @@ bool ClassType::AllowInstantiation() const {
return !IsExtern() || nspace()->IsDefaultNamespace();
}
void ClassType::Finalize() const {
if (is_finalized_) return;
CurrentScope::Scope scope_activator(alias_->ParentScope());
CurrentSourcePosition::Scope position_activator(decl_->pos);
if (parent()) {
if (const ClassType* super_class = ClassType::DynamicCast(parent())) {
has_indexed_field_ = super_class->HasIndexedField();
}
}
TypeVisitor::VisitClassFieldsAndMethods(const_cast<ClassType*>(this),
this->decl_);
is_finalized_ = true;
CheckForDuplicateFields();
}
void ClassType::GenerateAccessors() {
// For each field, construct AST snippets that implement a CSA accessor
// function and define a corresponding '.field' operator. The
// implementation iterator will turn the snippets into code.
for (auto& field : fields_) {
if (field.index) continue;
CurrentSourcePosition::Scope position_activator(field.pos);
IdentifierExpression* parameter =
MakeNode<IdentifierExpression>(MakeNode<Identifier>(std::string{"o"}));
// Load accessor
std::string camel_field_name = CamelifyString(field.name_and_type.name);
std::string load_macro_name = "Load" + this->name() + camel_field_name;
Signature load_signature;
load_signature.parameter_names.push_back(MakeNode<Identifier>("o"));
load_signature.parameter_types.types.push_back(this);
load_signature.parameter_types.var_args = false;
load_signature.return_type = field.name_and_type.type;
Statement* load_body =
MakeNode<ReturnStatement>(MakeNode<FieldAccessExpression>(
parameter, MakeNode<Identifier>(field.name_and_type.name)));
Declarations::DeclareMacro(load_macro_name, base::nullopt, load_signature,
false, load_body, base::nullopt, false);
// Store accessor
IdentifierExpression* value = MakeNode<IdentifierExpression>(
std::vector<std::string>{}, MakeNode<Identifier>(std::string{"v"}));
std::string store_macro_name = "Store" + this->name() + camel_field_name;
Signature store_signature;
store_signature.parameter_names.push_back(MakeNode<Identifier>("o"));
store_signature.parameter_names.push_back(MakeNode<Identifier>("v"));
store_signature.parameter_types.types.push_back(this);
store_signature.parameter_types.types.push_back(field.name_and_type.type);
store_signature.parameter_types.var_args = false;
// TODO(danno): Store macros probably should return their value argument
store_signature.return_type = TypeOracle::GetVoidType();
Statement* store_body =
MakeNode<ExpressionStatement>(MakeNode<AssignmentExpression>(
MakeNode<FieldAccessExpression>(
parameter, MakeNode<Identifier>(field.name_and_type.name)),
value));
Declarations::DeclareMacro(store_macro_name, base::nullopt, store_signature,
false, store_body, base::nullopt, false);
}
}
void PrintSignature(std::ostream& os, const Signature& sig, bool with_names) {
os << "(";
for (size_t i = 0; i < sig.parameter_types.types.size(); ++i) {

View File

@ -12,6 +12,8 @@
#include <vector>
#include "src/base/optional.h"
#include "src/torque/ast.h"
#include "src/torque/constants.h"
#include "src/torque/source-positions.h"
#include "src/torque/utils.h"
@ -19,38 +21,6 @@ namespace v8 {
namespace internal {
namespace torque {
static const char* const CONSTEXPR_TYPE_PREFIX = "constexpr ";
static const char* const NEVER_TYPE_STRING = "never";
static const char* const CONSTEXPR_BOOL_TYPE_STRING = "constexpr bool";
static const char* const CONSTEXPR_INTPTR_TYPE_STRING = "constexpr intptr";
static const char* const BOOL_TYPE_STRING = "bool";
static const char* const VOID_TYPE_STRING = "void";
static const char* const ARGUMENTS_TYPE_STRING = "Arguments";
static const char* const CONTEXT_TYPE_STRING = "Context";
static const char* const MAP_TYPE_STRING = "Map";
static const char* const OBJECT_TYPE_STRING = "Object";
static const char* const HEAP_OBJECT_TYPE_STRING = "HeapObject";
static const char* const JSOBJECT_TYPE_STRING = "JSObject";
static const char* const SMI_TYPE_STRING = "Smi";
static const char* const TAGGED_TYPE_STRING = "Tagged";
static const char* const RAWPTR_TYPE_STRING = "RawPtr";
static const char* const CONST_STRING_TYPE_STRING = "constexpr string";
static const char* const STRING_TYPE_STRING = "String";
static const char* const NUMBER_TYPE_STRING = "Number";
static const char* const BUILTIN_POINTER_TYPE_STRING = "BuiltinPtr";
static const char* const INTPTR_TYPE_STRING = "intptr";
static const char* const UINTPTR_TYPE_STRING = "uintptr";
static const char* const INT32_TYPE_STRING = "int32";
static const char* const UINT32_TYPE_STRING = "uint32";
static const char* const INT16_TYPE_STRING = "int16";
static const char* const UINT16_TYPE_STRING = "uint16";
static const char* const INT8_TYPE_STRING = "int8";
static const char* const UINT8_TYPE_STRING = "uint8";
static const char* const FLOAT64_TYPE_STRING = "float64";
static const char* const CONST_INT31_TYPE_STRING = "constexpr int31";
static const char* const CONST_INT32_TYPE_STRING = "constexpr int32";
static const char* const CONST_FLOAT64_TYPE_STRING = "constexpr float64";
class AggregateType;
struct Identifier;
class Macro;
@ -231,11 +201,13 @@ class AbstractType final : public Type {
}
std::string GetGeneratedTNodeTypeNameImpl() const override;
bool IsConstexpr() const override {
return name().substr(0, strlen(CONSTEXPR_TYPE_PREFIX)) ==
CONSTEXPR_TYPE_PREFIX;
bool is_constexpr = non_constexpr_version_ != nullptr;
DCHECK_EQ(is_constexpr, IsConstexprName(name()));
return is_constexpr;
}
const Type* NonConstexprVersion() const override {
if (IsConstexpr()) return *non_constexpr_version_;
if (non_constexpr_version_) return non_constexpr_version_;
return this;
}
@ -243,14 +215,16 @@ class AbstractType final : public Type {
friend class TypeOracle;
AbstractType(const Type* parent, bool transient, const std::string& name,
const std::string& generated_type,
base::Optional<const AbstractType*> non_constexpr_version)
const Type* non_constexpr_version)
: Type(Kind::kAbstractType, parent),
transient_(transient),
name_(name),
generated_type_(generated_type),
non_constexpr_version_(non_constexpr_version) {
DCHECK_EQ(non_constexpr_version_.has_value(), IsConstexpr());
if (parent) DCHECK(parent->IsConstexpr() == IsConstexpr());
DCHECK_EQ(!IsConstexprName(name), non_constexpr_version == nullptr);
DCHECK_IMPLIES(IsConstexprName(name),
!non_constexpr_version->IsConstexpr());
}
bool IsTransient() const override { return transient_; }
@ -258,7 +232,7 @@ class AbstractType final : public Type {
bool transient_;
const std::string name_;
const std::string generated_type_;
base::Optional<const AbstractType*> non_constexpr_version_;
const Type* non_constexpr_version_;
};
// For now, builtin pointers are restricted to Torque-defined builtins.
@ -439,10 +413,15 @@ class AggregateType : public Type {
std::string GetGeneratedTypeNameImpl() const override { UNREACHABLE(); }
std::string GetGeneratedTNodeTypeNameImpl() const override { UNREACHABLE(); }
virtual void Finalize() const = 0;
virtual bool HasIndexedField() const { return false; }
void SetFields(std::vector<Field> fields) { fields_ = std::move(fields); }
const std::vector<Field>& fields() const { return fields_; }
const std::vector<Field>& fields() const {
if (!is_finalized_) Finalize();
return fields_;
}
bool HasField(const std::string& name) const;
const Field& LookupField(const std::string& name) const;
const std::string& name() const { return name_; }
@ -458,23 +437,34 @@ class AggregateType : public Type {
}
void RegisterMethod(Method* method) { methods_.push_back(method); }
const std::vector<Method*>& Methods() const { return methods_; }
const std::vector<Method*>& Methods() const {
if (!is_finalized_) Finalize();
return methods_;
}
std::vector<Method*> Methods(const std::string& name) const;
std::vector<const AggregateType*> GetHierarchy();
std::vector<const AggregateType*> GetHierarchy() const;
protected:
AggregateType(Kind kind, const Type* parent, Namespace* nspace,
const std::string& name)
: Type(kind, parent), namespace_(nspace), name_(name) {}
: Type(kind, parent),
is_finalized_(false),
namespace_(nspace),
name_(name) {}
void CheckForDuplicateFields();
void CheckForDuplicateFields() const;
// Use this lookup if you do not want to trigger finalization on this type.
const Field& LookupFieldInternal(const std::string& name) const;
protected:
mutable bool is_finalized_;
std::vector<Field> fields_;
private:
Namespace* namespace_;
std::string name_;
std::vector<Method*> methods_;
std::vector<Field> fields_;
};
class StructType final : public AggregateType {
@ -486,13 +476,18 @@ class StructType final : public AggregateType {
private:
friend class TypeOracle;
StructType(Namespace* nspace, const std::string& name)
: AggregateType(Kind::kStructType, nullptr, nspace, name) {
: AggregateType(Kind::kStructType, nullptr, nspace, name) {}
void Finalize() const override {
is_finalized_ = true;
CheckForDuplicateFields();
}
const std::string& GetStructName() const { return name(); }
};
class TypeAlias;
class ClassType final : public AggregateType {
public:
DECLARE_TYPE_BOILERPLATE(ClassType)
@ -509,6 +504,7 @@ class ClassType final : public AggregateType {
return parent()->IsClassType() ? ClassType::DynamicCast(parent()) : nullptr;
}
void SetSize(size_t size) { size_ = size; }
void GenerateAccessors();
bool AllowInstantiation() const;
const Field& RegisterField(Field field) override {
if (field.index) {
@ -516,19 +512,24 @@ class ClassType final : public AggregateType {
}
return AggregateType::RegisterField(field);
}
void Finalize() const override;
private:
friend class TypeOracle;
friend class TypeVisitor;
ClassType(const Type* parent, Namespace* nspace, const std::string& name,
bool is_extern, bool generate_print, bool transient,
const std::string& generates);
const std::string& generates, const ClassDeclaration* decl,
const TypeAlias* alias);
bool is_extern_;
bool generate_print_;
bool transient_;
size_t size_;
bool has_indexed_field_;
mutable bool has_indexed_field_;
const std::string generates_;
const ClassDeclaration* decl_;
const TypeAlias* alias_;
};
inline std::ostream& operator<<(std::ostream& os, const Type& t) {
@ -574,7 +575,7 @@ class VisitResultVector : public std::vector<VisitResult> {
VisitResultVector() : std::vector<VisitResult>() {}
VisitResultVector(std::initializer_list<VisitResult> init)
: std::vector<VisitResult>(init) {}
TypeVector GetTypeVector() const {
TypeVector ComputeTypeVector() const {
TypeVector result;
for (auto& visit_result : *this) {
result.push_back(visit_result.type());

View File

@ -882,4 +882,18 @@ namespace test {
check(array.a == 2);
check(array.b == 9);
}
type Baztype = Foo | FooType;
extern class Foo extends JSObject { fooField: FooType; }
extern class Bar extends Foo {
barField: Bartype;
bazfield: Baztype;
}
type Bartype = FooType;
type FooType = Smi | Bar;
}