diff options
Diffstat (limited to 'deps/v8/src/torque')
32 files changed, 1656 insertions, 1064 deletions
diff --git a/deps/v8/src/torque/ast.h b/deps/v8/src/torque/ast.h index 23de121065..5ce25cf13a 100644 --- a/deps/v8/src/torque/ast.h +++ b/deps/v8/src/torque/ast.h @@ -46,8 +46,7 @@ namespace torque { #define AST_TYPE_EXPRESSION_NODE_KIND_LIST(V) \ V(BasicTypeExpression) \ V(FunctionTypeExpression) \ - V(UnionTypeExpression) \ - V(ReferenceTypeExpression) + V(UnionTypeExpression) #define AST_STATEMENT_NODE_KIND_LIST(V) \ V(BlockStatement) \ @@ -72,20 +71,17 @@ namespace torque { #define AST_DECLARATION_NODE_KIND_LIST(V) \ AST_TYPE_DECLARATION_NODE_KIND_LIST(V) \ - V(StandardDeclaration) \ V(GenericDeclaration) \ V(SpecializationDeclaration) \ V(ExternConstDeclaration) \ V(NamespaceDeclaration) \ V(ConstDeclaration) \ - V(CppIncludeDeclaration) - -#define AST_CALLABLE_NODE_KIND_LIST(V) \ - V(TorqueMacroDeclaration) \ - V(TorqueBuiltinDeclaration) \ - V(ExternalMacroDeclaration) \ - V(ExternalBuiltinDeclaration) \ - V(ExternalRuntimeDeclaration) \ + V(CppIncludeDeclaration) \ + V(TorqueMacroDeclaration) \ + V(TorqueBuiltinDeclaration) \ + V(ExternalMacroDeclaration) \ + V(ExternalBuiltinDeclaration) \ + V(ExternalRuntimeDeclaration) \ V(IntrinsicDeclaration) #define AST_NODE_KIND_LIST(V) \ @@ -93,7 +89,6 @@ namespace torque { AST_TYPE_EXPRESSION_NODE_KIND_LIST(V) \ AST_STATEMENT_NODE_KIND_LIST(V) \ AST_DECLARATION_NODE_KIND_LIST(V) \ - AST_CALLABLE_NODE_KIND_LIST(V) \ V(Identifier) \ V(LabelBlock) @@ -118,16 +113,16 @@ struct AstNodeClassCheck { }; // Boilerplate for most derived classes. -#define DEFINE_AST_NODE_LEAF_BOILERPLATE(T) \ - static const Kind kKind = Kind::k##T; \ - static T* cast(AstNode* node) { \ - if (node->kind != kKind) return nullptr; \ - return static_cast<T*>(node); \ - } \ - static T* DynamicCast(AstNode* node) { \ - if (!node) return nullptr; \ - if (!AstNodeClassCheck::IsInstanceOf<T>(node)) return nullptr; \ - return static_cast<T*>(node); \ +#define DEFINE_AST_NODE_LEAF_BOILERPLATE(T) \ + static const Kind kKind = Kind::k##T; \ + static T* cast(AstNode* node) { \ + DCHECK_EQ(node->kind, kKind); \ + return static_cast<T*>(node); \ + } \ + static T* DynamicCast(AstNode* node) { \ + if (!node) return nullptr; \ + if (node->kind != kKind) return nullptr; \ + return static_cast<T*>(node); \ } // Boilerplate for classes with subclasses. @@ -221,6 +216,10 @@ struct Identifier : AstNode { std::string value; }; +inline std::ostream& operator<<(std::ostream& os, Identifier* id) { + return os << id->value; +} + struct IdentifierPtrValueEq { bool operator()(const Identifier* a, const Identifier* b) { return a->value < b->value; @@ -252,11 +251,11 @@ struct IdentifierExpression : LocationExpression { struct IntrinsicCallExpression : Expression { DEFINE_AST_NODE_LEAF_BOILERPLATE(IntrinsicCallExpression) - IntrinsicCallExpression(SourcePosition pos, std::string name, + IntrinsicCallExpression(SourcePosition pos, Identifier* name, std::vector<TypeExpression*> generic_arguments, std::vector<Expression*> arguments) : Expression(kKind, pos), - name(std::move(name)), + name(name), generic_arguments(std::move(generic_arguments)), arguments(std::move(arguments)) {} @@ -267,7 +266,7 @@ struct IntrinsicCallExpression : Expression { callback(this); } - std::string name; + Identifier* name; std::vector<TypeExpression*> generic_arguments; std::vector<Expression*> arguments; }; @@ -619,13 +618,6 @@ struct UnionTypeExpression : TypeExpression { TypeExpression* b; }; -struct ReferenceTypeExpression : TypeExpression { - DEFINE_AST_NODE_LEAF_BOILERPLATE(ReferenceTypeExpression) - ReferenceTypeExpression(SourcePosition pos, TypeExpression* referenced_type) - : TypeExpression(kKind, pos), referenced_type(referenced_type) {} - TypeExpression* referenced_type; -}; - struct ExpressionStatement : Statement { DEFINE_AST_NODE_LEAF_BOILERPLATE(ExpressionStatement) ExpressionStatement(SourcePosition pos, Expression* expression) @@ -849,10 +841,15 @@ struct ConditionalAnnotation { ConditionalAnnotationType type; }; +struct Annotation { + Identifier* name; + base::Optional<std::string> param; +}; + struct ClassFieldExpression { NameAndTypeExpression name_and_type; base::Optional<std::string> index; - base::Optional<ConditionalAnnotation> conditional; + std::vector<ConditionalAnnotation> conditions; bool weak; bool const_qualified; bool generate_verify; @@ -865,34 +862,33 @@ struct LabelAndTypes { using LabelAndTypesVector = std::vector<LabelAndTypes>; -struct CallableNodeSignature { +struct CallableDeclaration : Declaration { + CallableDeclaration(AstNode::Kind kind, SourcePosition pos, + bool transitioning, Identifier* name, + ParameterList parameters, TypeExpression* return_type, + LabelAndTypesVector labels) + : Declaration(kind, pos), + transitioning(transitioning), + name(name), + parameters(std::move(parameters)), + return_type(return_type), + labels(std::move(labels)) {} + DEFINE_AST_NODE_INNER_BOILERPLATE(CallableDeclaration) + bool transitioning; + Identifier* name; ParameterList parameters; TypeExpression* return_type; LabelAndTypesVector labels; }; -struct CallableNode : AstNode { - CallableNode(AstNode::Kind kind, SourcePosition pos, bool transitioning, - std::string name, ParameterList parameters, - TypeExpression* return_type, const LabelAndTypesVector& labels) - : AstNode(kind, pos), - transitioning(transitioning), - name(std::move(name)), - signature(new CallableNodeSignature{parameters, return_type, labels}) {} - DEFINE_AST_NODE_INNER_BOILERPLATE(CallableNode) - bool transitioning; - std::string name; - std::unique_ptr<CallableNodeSignature> signature; -}; - -struct MacroDeclaration : CallableNode { +struct MacroDeclaration : CallableDeclaration { DEFINE_AST_NODE_INNER_BOILERPLATE(MacroDeclaration) MacroDeclaration(AstNode::Kind kind, SourcePosition pos, bool transitioning, - std::string name, base::Optional<std::string> op, + Identifier* name, base::Optional<std::string> op, ParameterList parameters, TypeExpression* return_type, const LabelAndTypesVector& labels) - : CallableNode(kind, pos, transitioning, std::move(name), - std::move(parameters), return_type, labels), + : CallableDeclaration(kind, pos, transitioning, name, + std::move(parameters), return_type, labels), op(std::move(op)) { if (parameters.implicit_kind == ImplicitKind::kJSImplicit) { Error("Cannot use \"js-implicit\" with macros, use \"implicit\" instead.") @@ -906,23 +902,22 @@ struct ExternalMacroDeclaration : MacroDeclaration { DEFINE_AST_NODE_LEAF_BOILERPLATE(ExternalMacroDeclaration) ExternalMacroDeclaration(SourcePosition pos, bool transitioning, std::string external_assembler_name, - std::string name, base::Optional<std::string> op, + Identifier* name, base::Optional<std::string> op, ParameterList parameters, TypeExpression* return_type, const LabelAndTypesVector& labels) - : MacroDeclaration(kKind, pos, transitioning, std::move(name), - std::move(op), std::move(parameters), return_type, - labels), + : MacroDeclaration(kKind, pos, transitioning, name, std::move(op), + std::move(parameters), return_type, labels), external_assembler_name(std::move(external_assembler_name)) {} std::string external_assembler_name; }; -struct IntrinsicDeclaration : CallableNode { +struct IntrinsicDeclaration : CallableDeclaration { DEFINE_AST_NODE_LEAF_BOILERPLATE(IntrinsicDeclaration) - IntrinsicDeclaration(SourcePosition pos, std::string name, + IntrinsicDeclaration(SourcePosition pos, Identifier* name, ParameterList parameters, TypeExpression* return_type) - : CallableNode(kKind, pos, false, std::move(name), std::move(parameters), - return_type, {}) { + : CallableDeclaration(kKind, pos, false, name, std::move(parameters), + return_type, {}) { if (parameters.implicit_kind != ImplicitKind::kNoImplicit) { Error("Intinsics cannot have implicit parameters."); } @@ -932,24 +927,26 @@ struct IntrinsicDeclaration : CallableNode { struct TorqueMacroDeclaration : MacroDeclaration { DEFINE_AST_NODE_LEAF_BOILERPLATE(TorqueMacroDeclaration) TorqueMacroDeclaration(SourcePosition pos, bool transitioning, - std::string name, base::Optional<std::string> op, + Identifier* name, base::Optional<std::string> op, ParameterList parameters, TypeExpression* return_type, - const LabelAndTypesVector& labels, bool export_to_csa) - : MacroDeclaration(kKind, pos, transitioning, std::move(name), - std::move(op), std::move(parameters), return_type, - labels), - export_to_csa(export_to_csa) {} + const LabelAndTypesVector& labels, bool export_to_csa, + base::Optional<Statement*> body) + : MacroDeclaration(kKind, pos, transitioning, name, std::move(op), + std::move(parameters), return_type, labels), + export_to_csa(export_to_csa), + body(body) {} bool export_to_csa; + base::Optional<Statement*> body; }; -struct BuiltinDeclaration : CallableNode { +struct BuiltinDeclaration : CallableDeclaration { DEFINE_AST_NODE_INNER_BOILERPLATE(BuiltinDeclaration) BuiltinDeclaration(AstNode::Kind kind, SourcePosition pos, bool javascript_linkage, bool transitioning, - std::string name, ParameterList parameters, + Identifier* name, ParameterList parameters, TypeExpression* return_type) - : CallableNode(kind, pos, transitioning, std::move(name), - std::move(parameters), return_type, {}), + : CallableDeclaration(kind, pos, transitioning, name, + std::move(parameters), return_type, {}), javascript_linkage(javascript_linkage) { if (parameters.implicit_kind == ImplicitKind::kJSImplicit && !javascript_linkage) { @@ -971,32 +968,33 @@ struct BuiltinDeclaration : CallableNode { struct ExternalBuiltinDeclaration : BuiltinDeclaration { DEFINE_AST_NODE_LEAF_BOILERPLATE(ExternalBuiltinDeclaration) ExternalBuiltinDeclaration(SourcePosition pos, bool transitioning, - bool javascript_linkage, std::string name, + bool javascript_linkage, Identifier* name, ParameterList parameters, TypeExpression* return_type) - : BuiltinDeclaration(kKind, pos, javascript_linkage, transitioning, - std::move(name), std::move(parameters), - return_type) {} + : BuiltinDeclaration(kKind, pos, javascript_linkage, transitioning, name, + std::move(parameters), return_type) {} }; struct TorqueBuiltinDeclaration : BuiltinDeclaration { DEFINE_AST_NODE_LEAF_BOILERPLATE(TorqueBuiltinDeclaration) TorqueBuiltinDeclaration(SourcePosition pos, bool transitioning, - bool javascript_linkage, std::string name, + bool javascript_linkage, Identifier* name, ParameterList parameters, - TypeExpression* return_type) - : BuiltinDeclaration(kKind, pos, javascript_linkage, transitioning, - std::move(name), std::move(parameters), - return_type) {} + TypeExpression* return_type, + base::Optional<Statement*> body) + : BuiltinDeclaration(kKind, pos, javascript_linkage, transitioning, name, + std::move(parameters), return_type), + body(body) {} + base::Optional<Statement*> body; }; -struct ExternalRuntimeDeclaration : CallableNode { +struct ExternalRuntimeDeclaration : CallableDeclaration { DEFINE_AST_NODE_LEAF_BOILERPLATE(ExternalRuntimeDeclaration) ExternalRuntimeDeclaration(SourcePosition pos, bool transitioning, - std::string name, ParameterList parameters, + Identifier* name, ParameterList parameters, TypeExpression* return_type) - : CallableNode(kKind, pos, transitioning, name, parameters, return_type, - {}) {} + : CallableDeclaration(kKind, pos, transitioning, name, parameters, + return_type, {}) {} }; struct ConstDeclaration : Declaration { @@ -1012,47 +1010,32 @@ struct ConstDeclaration : Declaration { Expression* expression; }; -struct StandardDeclaration : Declaration { - DEFINE_AST_NODE_LEAF_BOILERPLATE(StandardDeclaration) - StandardDeclaration(SourcePosition pos, CallableNode* callable, - base::Optional<Statement*> body) - : Declaration(kKind, pos), callable(callable), body(body) {} - CallableNode* callable; - base::Optional<Statement*> body; -}; - struct GenericDeclaration : Declaration { DEFINE_AST_NODE_LEAF_BOILERPLATE(GenericDeclaration) - GenericDeclaration(SourcePosition pos, CallableNode* callable, + GenericDeclaration(SourcePosition pos, std::vector<Identifier*> generic_parameters, - base::Optional<Statement*> body = base::nullopt) + CallableDeclaration* declaration) : Declaration(kKind, pos), - callable(callable), generic_parameters(std::move(generic_parameters)), - body(body) {} - CallableNode* callable; + declaration(declaration) {} std::vector<Identifier*> generic_parameters; - base::Optional<Statement*> body; + CallableDeclaration* declaration; }; -struct SpecializationDeclaration : Declaration { +struct SpecializationDeclaration : CallableDeclaration { DEFINE_AST_NODE_LEAF_BOILERPLATE(SpecializationDeclaration) - SpecializationDeclaration(SourcePosition pos, Identifier* name, + SpecializationDeclaration(SourcePosition pos, bool transitioning, + Identifier* name, std::vector<TypeExpression*> generic_parameters, ParameterList parameters, TypeExpression* return_type, - LabelAndTypesVector labels, Statement* b) - : Declaration(kKind, pos), - name(name), - external(false), + LabelAndTypesVector labels, Statement* body) + : CallableDeclaration(kKind, pos, transitioning, name, + std::move(parameters), return_type, + std::move(labels)), generic_parameters(std::move(generic_parameters)), - signature(new CallableNodeSignature{std::move(parameters), return_type, - std::move(labels)}), - body(b) {} - Identifier* name; - bool external; + body(body) {} std::vector<TypeExpression*> generic_parameters; - std::unique_ptr<CallableNodeSignature> signature; Statement* body; }; diff --git a/deps/v8/src/torque/class-debug-reader-generator.cc b/deps/v8/src/torque/class-debug-reader-generator.cc new file mode 100644 index 0000000000..6abdffcc91 --- /dev/null +++ b/deps/v8/src/torque/class-debug-reader-generator.cc @@ -0,0 +1,222 @@ +// 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. + +#include "src/flags/flags.h" +#include "src/torque/implementation-visitor.h" +#include "src/torque/type-oracle.h" + +namespace v8 { +namespace internal { +namespace torque { + +namespace { +void GenerateClassDebugReader(const ClassType& type, std::ostream& h_contents, + std::ostream& cc_contents, std::ostream& visitor, + std::unordered_set<const ClassType*>* done) { + // Make sure each class only gets generated once. + if (!type.IsExtern() || !done->insert(&type).second) return; + const ClassType* super_type = type.GetSuperClass(); + + // We must emit the classes in dependency order. If the super class hasn't + // been emitted yet, go handle it first. + if (super_type != nullptr) { + GenerateClassDebugReader(*super_type, h_contents, cc_contents, visitor, + done); + } + + const std::string name = type.name(); + const std::string super_name = + super_type == nullptr ? "Object" : super_type->name(); + h_contents << "\nclass Tq" << name << " : public Tq" << super_name << " {\n"; + h_contents << " public:\n"; + h_contents << " inline Tq" << name << "(uintptr_t address) : Tq" + << super_name << "(address) {}\n"; + h_contents << " std::vector<std::unique_ptr<ObjectProperty>> " + "GetProperties(d::MemoryAccessor accessor) const override;\n"; + h_contents << " const char* GetName() const override;\n"; + h_contents << " void Visit(TqObjectVisitor* visitor) const override;\n"; + + cc_contents << "\nconst char* Tq" << name << "::GetName() const {\n"; + cc_contents << " return \"v8::internal::" << name << "\";\n"; + cc_contents << "}\n"; + + cc_contents << "\nvoid Tq" << name + << "::Visit(TqObjectVisitor* visitor) const {\n"; + cc_contents << " visitor->Visit" << name << "(this);\n"; + cc_contents << "}\n"; + + visitor << " virtual void Visit" << name << "(const Tq" << name + << "* object) {\n"; + visitor << " Visit" << super_name << "(object);\n"; + visitor << " }\n"; + + std::stringstream get_props_impl; + + for (const Field& field : type.fields()) { + const Type* field_type = field.name_and_type.type; + if (field_type == TypeOracle::GetVoidType()) continue; + const std::string& field_name = field.name_and_type.name; + bool is_field_tagged = field_type->IsSubtypeOf(TypeOracle::GetTaggedType()); + base::Optional<const ClassType*> field_class_type = + field_type->ClassSupertype(); + size_t field_size = 0; + std::string field_size_string; + std::tie(field_size, field_size_string) = field.GetFieldSizeInformation(); + + std::string field_value_type; + std::string field_value_type_compressed; + std::string field_cc_type; + std::string field_cc_type_compressed; + if (is_field_tagged) { + field_value_type = "uintptr_t"; + field_value_type_compressed = "i::Tagged_t"; + field_cc_type = "v8::internal::" + (field_class_type.has_value() + ? (*field_class_type)->name() + : "Object"); + field_cc_type_compressed = + COMPRESS_POINTERS_BOOL ? "v8::internal::TaggedValue" : field_cc_type; + } else { + const Type* constexpr_version = field_type->ConstexprVersion(); + if (constexpr_version == nullptr) { + Error("Type '", field_type->ToString(), + "' requires a constexpr representation"); + continue; + } + field_cc_type = constexpr_version->GetGeneratedTypeName(); + field_cc_type_compressed = field_cc_type; + // Note that we need constexpr names to resolve correctly in the global + // namespace, because we're passing them as strings to a debugging + // extension. We can verify this during build of the debug helper, because + // we use this type for a local variable below, and generate this code in + // a disjoint namespace. However, we can't emit a useful error at this + // point. Instead we'll emit a comment that might be helpful. + field_value_type = + field_cc_type + + " /*Failing? Ensure constexpr type name is fully qualified and " + "necessary #includes are in debug-helper-internal.h*/"; + field_value_type_compressed = field_value_type; + } + + const std::string field_getter = + "Get" + CamelifyString(field_name) + "Value"; + const std::string address_getter = + "Get" + CamelifyString(field_name) + "Address"; + + std::string indexed_field_info; + std::string index_param; + std::string index_offset; + if (field.index) { + const Type* index_type = (*field.index)->name_and_type.type; + std::string index_type_name; + std::string index_value; + if (index_type == TypeOracle::GetSmiType()) { + index_type_name = "uintptr_t"; + index_value = + "i::PlatformSmiTagging::SmiToInt(indexed_field_count.value)"; + } else if (!index_type->IsSubtypeOf(TypeOracle::GetTaggedType())) { + const Type* constexpr_index = index_type->ConstexprVersion(); + if (constexpr_index == nullptr) { + Error("Type '", index_type->ToString(), + "' requires a constexpr representation"); + continue; + } + index_type_name = constexpr_index->GetGeneratedTypeName(); + index_value = "indexed_field_count.value"; + } else { + Error("Unsupported index type: ", index_type); + continue; + } + get_props_impl << " Value<" << index_type_name + << "> indexed_field_count = Get" + << CamelifyString((*field.index)->name_and_type.name) + << "Value(accessor);\n"; + indexed_field_info = + ", " + index_value + ", GetArrayKind(indexed_field_count.validity)"; + index_param = ", size_t offset"; + index_offset = " + offset * sizeof(value)"; + } + get_props_impl + << " result.push_back(v8::base::make_unique<ObjectProperty>(\"" + << field_name << "\", \"" << field_cc_type_compressed << "\", \"" + << field_cc_type << "\", " << address_getter << "()" + << indexed_field_info << "));\n"; + + h_contents << " uintptr_t " << address_getter << "() const;\n"; + h_contents << " Value<" << field_value_type << "> " << field_getter + << "(d::MemoryAccessor accessor " << index_param << ") const;\n"; + cc_contents << "\nuintptr_t Tq" << name << "::" << address_getter + << "() const {\n"; + cc_contents << " return address_ - i::kHeapObjectTag + " << field.offset + << ";\n"; + cc_contents << "}\n"; + cc_contents << "\nValue<" << field_value_type << "> Tq" << name + << "::" << field_getter << "(d::MemoryAccessor accessor" + << index_param << ") const {\n"; + cc_contents << " " << field_value_type_compressed << " value{};\n"; + cc_contents << " d::MemoryAccessResult validity = accessor(" + << address_getter << "()" << index_offset + << ", reinterpret_cast<uint8_t*>(&value), sizeof(value));\n"; + cc_contents << " return {validity, " + << (is_field_tagged ? "Decompress(value, address_)" : "value") + << "};\n"; + cc_contents << "}\n"; + } + + h_contents << "};\n"; + + cc_contents << "\nstd::vector<std::unique_ptr<ObjectProperty>> Tq" << name + << "::GetProperties(d::MemoryAccessor accessor) const {\n"; + cc_contents << " std::vector<std::unique_ptr<ObjectProperty>> result = Tq" + << super_name << "::GetProperties(accessor);\n"; + cc_contents << get_props_impl.str(); + cc_contents << " return result;\n"; + cc_contents << "}\n"; +} +} // namespace + +void ImplementationVisitor::GenerateClassDebugReaders( + const std::string& output_directory) { + const std::string file_name = "class-debug-readers-tq"; + std::stringstream h_contents; + std::stringstream cc_contents; + h_contents << "// Provides the ability to read object properties in\n"; + h_contents << "// postmortem or remote scenarios, where the debuggee's\n"; + h_contents << "// memory is not part of the current process's address\n"; + h_contents << "// space and must be read using a callback function.\n\n"; + { + IncludeGuardScope include_guard(h_contents, file_name + ".h"); + + h_contents << "#include <cstdint>\n"; + h_contents << "#include <vector>\n"; + h_contents + << "\n#include \"tools/debug_helper/debug-helper-internal.h\"\n\n"; + + cc_contents << "#include \"torque-generated/" << file_name << ".h\"\n"; + cc_contents << "#include \"include/v8-internal.h\"\n\n"; + cc_contents << "namespace i = v8::internal;\n\n"; + + NamespaceScope h_namespaces(h_contents, {"v8_debug_helper_internal"}); + NamespaceScope cc_namespaces(cc_contents, {"v8_debug_helper_internal"}); + + std::stringstream visitor; + visitor << "\nclass TqObjectVisitor {\n"; + visitor << " public:\n"; + visitor << " virtual void VisitObject(const TqObject* object) {}\n"; + + std::unordered_set<const ClassType*> done; + for (const TypeAlias* alias : GlobalContext::GetClasses()) { + const ClassType* type = ClassType::DynamicCast(alias->type()); + GenerateClassDebugReader(*type, h_contents, cc_contents, visitor, &done); + } + + visitor << "};\n"; + h_contents << visitor.str(); + } + WriteFile(output_directory + "/" + file_name + ".h", h_contents.str()); + WriteFile(output_directory + "/" + file_name + ".cc", cc_contents.str()); +} + +} // namespace torque +} // namespace internal +} // namespace v8 diff --git a/deps/v8/src/torque/constants.h b/deps/v8/src/torque/constants.h index 4ad3a6ec3c..efbbf9588e 100644 --- a/deps/v8/src/torque/constants.h +++ b/deps/v8/src/torque/constants.h @@ -28,6 +28,7 @@ static const char* const JS_FUNCTION_TYPE_STRING = "JSFunction"; 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 JSANY_TYPE_STRING = "JSAny"; static const char* const JSOBJECT_TYPE_STRING = "JSObject"; static const char* const SMI_TYPE_STRING = "Smi"; static const char* const TAGGED_TYPE_STRING = "Tagged"; @@ -49,6 +50,10 @@ 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"; +static const char* const TORQUE_INTERNAL_NAMESPACE_STRING = "torque_internal"; +static const char* const REFERENCE_TYPE_STRING = "Reference"; +static const char* const SLICE_TYPE_STRING = "Slice"; +static const char* const STRUCT_NAMESPACE_STRING = "_struct"; inline bool IsConstexprName(const std::string& name) { return name.substr(0, std::strlen(CONSTEXPR_TYPE_PREFIX)) == diff --git a/deps/v8/src/torque/contextual.h b/deps/v8/src/torque/contextual.h index 92d2bdf3d7..d7764bfa68 100644 --- a/deps/v8/src/torque/contextual.h +++ b/deps/v8/src/torque/contextual.h @@ -15,7 +15,7 @@ namespace internal { namespace torque { template <class Variable> -V8_EXPORT_PRIVATE typename Variable::VariableType*& ContextualVariableTop(); +V8_EXPORT_PRIVATE typename Variable::Scope*& ContextualVariableTop(); // {ContextualVariable} provides a clean alternative to a global variable. // The contextual variable is mutable, and supports managing the value of @@ -30,8 +30,6 @@ V8_EXPORT_PRIVATE typename Variable::VariableType*& ContextualVariableTop(); template <class Derived, class VarType> class ContextualVariable { public: - using VariableType = VarType; - // A {Scope} contains a new object of type {VarType} and gives // ContextualVariable::Get() access to it. Upon destruction, the contextual // variable is restored to the state before the {Scope} was created. Scopes @@ -41,18 +39,20 @@ class ContextualVariable { public: template <class... Args> explicit Scope(Args&&... args) - : current_(std::forward<Args>(args)...), previous_(Top()) { - Top() = ¤t_; + : value_(std::forward<Args>(args)...), previous_(Top()) { + Top() = this; } ~Scope() { // Ensure stack discipline. - DCHECK_EQ(¤t_, Top()); + DCHECK_EQ(this, Top()); Top() = previous_; } + VarType& Value() { return value_; } + private: - VarType current_; - VarType* previous_; + VarType value_; + Scope* previous_; static_assert(std::is_base_of<ContextualVariable, Derived>::value, "Curiously Recurring Template Pattern"); @@ -65,13 +65,13 @@ class ContextualVariable { // for this contextual variable. static VarType& Get() { DCHECK_NOT_NULL(Top()); - return *Top(); + return Top()->Value(); } private: template <class T> - friend typename T::VariableType*& ContextualVariableTop(); - static VarType*& Top() { return ContextualVariableTop<Derived>(); } + friend typename T::Scope*& ContextualVariableTop(); + static Scope*& Top() { return ContextualVariableTop<Derived>(); } static bool HasScope() { return Top() != nullptr; } friend class MessageBuilder; @@ -82,11 +82,11 @@ class ContextualVariable { struct VarName \ : v8::internal::torque::ContextualVariable<VarName, __VA_ARGS__> {} -#define DEFINE_CONTEXTUAL_VARIABLE(VarName) \ - template <> \ - V8_EXPORT_PRIVATE VarName::VariableType*& ContextualVariableTop<VarName>() { \ - static thread_local VarName::VariableType* top = nullptr; \ - return top; \ +#define DEFINE_CONTEXTUAL_VARIABLE(VarName) \ + template <> \ + V8_EXPORT_PRIVATE VarName::Scope*& ContextualVariableTop<VarName>() { \ + static thread_local VarName::Scope* top = nullptr; \ + return top; \ } // By inheriting from {ContextualClass} a class can become a contextual variable diff --git a/deps/v8/src/torque/csa-generator.cc b/deps/v8/src/torque/csa-generator.cc index cd7ff22c48..0c49033955 100644 --- a/deps/v8/src/torque/csa-generator.cc +++ b/deps/v8/src/torque/csa-generator.cc @@ -56,14 +56,10 @@ Stack<std::string> CSAGenerator::EmitBlock(const Block* block) { } void CSAGenerator::EmitSourcePosition(SourcePosition pos, bool always_emit) { - std::string file = SourceFileMap::AbsolutePath(pos.source); + const std::string& file = SourceFileMap::AbsolutePath(pos.source); if (always_emit || !previous_position_.CompareStartIgnoreColumn(pos)) { // Lines in Torque SourcePositions are zero-based, while the // CodeStubAssembler and downwind systems are one-based. - for (auto& c : file) { - if (c == '\\') - c = '/'; - } out_ << " ca_.SetSourcePosition(\"" << file << "\", " << (pos.start.line + 1) << ");\n"; previous_position_ = pos; @@ -309,8 +305,7 @@ void CSAGenerator::EmitInstruction(const CallCsaMacroInstruction& instruction, std::string catch_name = PreCallableExceptionPreparation(instruction.catch_block); out_ << " "; - bool needs_flattening = - return_type->IsStructType() || return_type->IsReferenceType(); + bool needs_flattening = return_type->IsStructType(); if (needs_flattening) { out_ << "std::tie("; PrintCommaSeparatedList(out_, results); @@ -713,8 +708,13 @@ void CSAGenerator::EmitInstruction(const UnsafeCastInstruction& instruction, void CSAGenerator::EmitInstruction( const CreateFieldReferenceInstruction& instruction, Stack<std::string>* stack) { - const Field& field = - instruction.class_type->LookupField(instruction.field_name); + base::Optional<const ClassType*> class_type = + instruction.type->ClassSupertype(); + if (!class_type.has_value()) { + ReportError("Cannot create field reference of type ", instruction.type, + " which does not inherit from a class type"); + } + const Field& field = class_type.value()->LookupField(instruction.field_name); std::string offset_name = FreshNodeName(); stack->Push(offset_name); @@ -770,11 +770,6 @@ void CSAGenerator::EmitCSAValue(VisitResult result, out); } out << "}"; - } else if (result.type()->IsReferenceType()) { - DCHECK_EQ(2, result.stack_range().Size()); - size_t offset = result.stack_range().begin().offset; - out << "CodeStubAssembler::Reference{" << values.Peek(BottomOffset{offset}) - << ", " << values.Peek(BottomOffset{offset + 1}) << "}"; } else { DCHECK_EQ(1, result.stack_range().Size()); out << "compiler::TNode<" << result.type()->GetGeneratedTNodeTypeName() diff --git a/deps/v8/src/torque/declarable.cc b/deps/v8/src/torque/declarable.cc index 1fd07d5b0d..5bcaff016d 100644 --- a/deps/v8/src/torque/declarable.cc +++ b/deps/v8/src/torque/declarable.cc @@ -7,6 +7,7 @@ #include "src/torque/declarable.h" #include "src/torque/global-context.h" +#include "src/torque/type-inference.h" #include "src/torque/type-visitor.h" namespace v8 { @@ -58,67 +59,38 @@ std::ostream& operator<<(std::ostream& os, const RuntimeFunction& b) { std::ostream& operator<<(std::ostream& os, const Generic& g) { os << "generic " << g.name() << "<"; PrintCommaSeparatedList( - os, g.declaration()->generic_parameters, + os, g.generic_parameters(), [](const Identifier* identifier) { return identifier->value; }); os << ">"; return os; } -namespace { -base::Optional<const Type*> InferTypeArgument(const std::string& to_infer, - TypeExpression* parameter, - const Type* argument) { - BasicTypeExpression* basic = BasicTypeExpression::DynamicCast(parameter); - if (basic && basic->namespace_qualification.empty() && !basic->is_constexpr && - basic->name == to_infer) { - return argument; - } - auto* ref = ReferenceTypeExpression::DynamicCast(parameter); - if (ref && argument->IsReferenceType()) { - return InferTypeArgument(to_infer, ref->referenced_type, - ReferenceType::cast(argument)->referenced_type()); - } - return base::nullopt; -} - -base::Optional<const Type*> InferTypeArgument( - const std::string& to_infer, const std::vector<TypeExpression*>& parameters, +TypeArgumentInference Generic::InferSpecializationTypes( + const TypeVector& explicit_specialization_types, const TypeVector& arguments) { - for (size_t i = 0; i < arguments.size() && i < parameters.size(); ++i) { - if (base::Optional<const Type*> inferred = - InferTypeArgument(to_infer, parameters[i], arguments[i])) { - return *inferred; - } - } - return base::nullopt; + size_t implicit_count = declaration()->parameters.implicit_count; + const std::vector<TypeExpression*>& parameters = + declaration()->parameters.types; + std::vector<TypeExpression*> explicit_parameters( + parameters.begin() + implicit_count, parameters.end()); + + CurrentScope::Scope generic_scope(ParentScope()); + TypeArgumentInference inference(generic_parameters(), + explicit_specialization_types, + explicit_parameters, arguments); + return inference; } -} // namespace - -base::Optional<TypeVector> Generic::InferSpecializationTypes( - const TypeVector& explicit_specialization_types, - const TypeVector& arguments) { - TypeVector result = explicit_specialization_types; - size_t type_parameter_count = declaration()->generic_parameters.size(); - if (explicit_specialization_types.size() > type_parameter_count) { +base::Optional<Statement*> Generic::CallableBody() { + if (auto* decl = TorqueMacroDeclaration::DynamicCast(declaration())) { + return decl->body; + } else if (auto* decl = + TorqueBuiltinDeclaration::DynamicCast(declaration())) { + return decl->body; + } else { return base::nullopt; } - for (size_t i = explicit_specialization_types.size(); - i < type_parameter_count; ++i) { - const std::string type_name = declaration()->generic_parameters[i]->value; - size_t implicit_count = - declaration()->callable->signature->parameters.implicit_count; - const std::vector<TypeExpression*>& parameters = - declaration()->callable->signature->parameters.types; - std::vector<TypeExpression*> explicit_parameters( - parameters.begin() + implicit_count, parameters.end()); - base::Optional<const Type*> inferred = - InferTypeArgument(type_name, explicit_parameters, arguments); - if (!inferred) return base::nullopt; - result.push_back(*inferred); - } - return result; } bool Namespace::IsDefaultNamespace() const { diff --git a/deps/v8/src/torque/declarable.h b/deps/v8/src/torque/declarable.h index cf6fd2554b..502180953d 100644 --- a/deps/v8/src/torque/declarable.h +++ b/deps/v8/src/torque/declarable.h @@ -21,6 +21,7 @@ namespace torque { class Scope; class Namespace; +class TypeArgumentInference; DECLARE_CONTEXTUAL_VARIABLE(CurrentScope, Scope*); @@ -261,6 +262,7 @@ class Callable : public Scope { const std::string& ExternalName() const { return external_name_; } const std::string& ReadableName() const { return readable_name_; } const Signature& signature() const { return signature_; } + bool IsTransitioning() const { return signature().transitioning; } const NameVector& parameter_names() const { return signature_.parameter_names; } @@ -269,7 +271,6 @@ class Callable : public Scope { } void IncrementReturns() { ++returns_; } bool HasReturns() const { return returns_; } - bool IsTransitioning() const { return transitioning_; } base::Optional<Statement*> body() const { return body_; } bool IsExternal() const { return !body_.has_value(); } virtual bool ShouldBeInlined() const { return false; } @@ -277,14 +278,13 @@ class Callable : public Scope { protected: Callable(Declarable::Kind kind, std::string external_name, - std::string readable_name, Signature signature, bool transitioning, + std::string readable_name, Signature signature, base::Optional<Statement*> body) : Scope(kind), external_name_(std::move(external_name)), readable_name_(std::move(readable_name)), signature_(std::move(signature)), - transitioning_(transitioning), returns_(0), body_(body) { DCHECK(!body || *body); @@ -294,7 +294,6 @@ class Callable : public Scope { std::string external_name_; std::string readable_name_; Signature signature_; - bool transitioning_; size_t returns_; base::Optional<Statement*> body_; }; @@ -320,9 +319,9 @@ class Macro : public Callable { protected: Macro(Declarable::Kind kind, std::string external_name, std::string readable_name, const Signature& signature, - bool transitioning, base::Optional<Statement*> body) + base::Optional<Statement*> body) : Callable(kind, std::move(external_name), std::move(readable_name), - signature, transitioning, body), + signature, body), used_(false) { if (signature.parameter_types.var_args) { ReportError("Varargs are not supported for macros."); @@ -344,9 +343,9 @@ class ExternMacro : public Macro { private: friend class Declarations; ExternMacro(const std::string& name, std::string external_assembler_name, - Signature signature, bool transitioning) + Signature signature) : Macro(Declarable::kExternMacro, name, name, std::move(signature), - transitioning, base::nullopt), + base::nullopt), external_assembler_name_(std::move(external_assembler_name)) {} std::string external_assembler_name_; @@ -360,10 +359,10 @@ class TorqueMacro : public Macro { protected: TorqueMacro(Declarable::Kind kind, std::string external_name, std::string readable_name, const Signature& signature, - bool transitioning, base::Optional<Statement*> body, - bool is_user_defined, bool exported_to_csa) + base::Optional<Statement*> body, bool is_user_defined, + bool exported_to_csa) : Macro(kind, std::move(external_name), std::move(readable_name), - signature, transitioning, body), + signature, body), exported_to_csa_(exported_to_csa) { SetIsUserDefined(is_user_defined); } @@ -371,12 +370,11 @@ class TorqueMacro : public Macro { private: friend class Declarations; TorqueMacro(std::string external_name, std::string readable_name, - const Signature& signature, bool transitioning, - base::Optional<Statement*> body, bool is_user_defined, - bool exported_to_csa) + const Signature& signature, base::Optional<Statement*> body, + bool is_user_defined, bool exported_to_csa) : TorqueMacro(Declarable::kTorqueMacro, std::move(external_name), - std::move(readable_name), signature, transitioning, body, - is_user_defined, exported_to_csa) {} + std::move(readable_name), signature, body, is_user_defined, + exported_to_csa) {} bool exported_to_csa_ = false; }; @@ -395,11 +393,9 @@ class Method : public TorqueMacro { private: friend class Declarations; Method(AggregateType* aggregate_type, std::string external_name, - std::string readable_name, const Signature& signature, - bool transitioning, Statement* body) + std::string readable_name, const Signature& signature, Statement* body) : TorqueMacro(Declarable::kMethod, std::move(external_name), - std::move(readable_name), signature, transitioning, body, - true, false), + std::move(readable_name), signature, body, true, false), aggregate_type_(aggregate_type) {} AggregateType* aggregate_type_; }; @@ -416,10 +412,10 @@ class Builtin : public Callable { private: friend class Declarations; Builtin(std::string external_name, std::string readable_name, - Builtin::Kind kind, const Signature& signature, bool transitioning, + Builtin::Kind kind, const Signature& signature, base::Optional<Statement*> body) : Callable(Declarable::kBuiltin, std::move(external_name), - std::move(readable_name), signature, transitioning, body), + std::move(readable_name), signature, body), kind_(kind) {} Kind kind_; @@ -431,10 +427,9 @@ class RuntimeFunction : public Callable { private: friend class Declarations; - RuntimeFunction(const std::string& name, const Signature& signature, - bool transitioning) + RuntimeFunction(const std::string& name, const Signature& signature) : Callable(Declarable::kRuntimeFunction, name, name, signature, - transitioning, base::nullopt) {} + base::nullopt) {} }; class Intrinsic : public Callable { @@ -444,8 +439,7 @@ class Intrinsic : public Callable { private: friend class Declarations; Intrinsic(std::string name, const Signature& signature) - : Callable(Declarable::kIntrinsic, name, name, signature, false, - base::nullopt) { + : Callable(Declarable::kIntrinsic, name, name, signature, base::nullopt) { if (signature.parameter_types.var_args) { ReportError("Varargs are not supported for intrinsics."); } @@ -483,33 +477,32 @@ class Generic : public Declarable { DECLARE_DECLARABLE_BOILERPLATE(Generic, generic) const std::string& name() const { return name_; } - GenericDeclaration* declaration() const { return declaration_; } + CallableDeclaration* declaration() const { + return generic_declaration_->declaration; + } const std::vector<Identifier*> generic_parameters() const { - return declaration()->generic_parameters; + return generic_declaration_->generic_parameters; } SpecializationMap<Callable>& specializations() { return specializations_; } - base::Optional<TypeVector> InferSpecializationTypes( + base::Optional<Statement*> CallableBody(); + + TypeArgumentInference InferSpecializationTypes( const TypeVector& explicit_specialization_types, const TypeVector& arguments); private: friend class Declarations; - Generic(const std::string& name, GenericDeclaration* declaration) + Generic(const std::string& name, GenericDeclaration* generic_declaration) : Declarable(Declarable::kGeneric), name_(name), - declaration_(declaration) {} + generic_declaration_(generic_declaration) {} std::string name_; - GenericDeclaration* declaration_; + GenericDeclaration* generic_declaration_; SpecializationMap<Callable> specializations_; }; -struct SpecializationKey { - Generic* generic; - TypeVector specialized_types; -}; - class GenericStructType : public Declarable { public: DECLARE_DECLARABLE_BOILERPLATE(GenericStructType, generic_type) diff --git a/deps/v8/src/torque/declaration-visitor.cc b/deps/v8/src/torque/declaration-visitor.cc index e0e996f33b..f762337463 100644 --- a/deps/v8/src/torque/declaration-visitor.cc +++ b/deps/v8/src/torque/declaration-visitor.cc @@ -53,26 +53,13 @@ void DeclarationVisitor::Visit(Declaration* decl) { } } -void DeclarationVisitor::Visit(CallableNode* decl, const Signature& signature, - base::Optional<Statement*> body) { - switch (decl->kind) { -#define ENUM_ITEM(name) \ - case AstNode::Kind::k##name: \ - return Visit(name::cast(decl), signature, body); - AST_CALLABLE_NODE_KIND_LIST(ENUM_ITEM) -#undef ENUM_ITEM - default: - UNIMPLEMENTED(); - } -} - Builtin* DeclarationVisitor::CreateBuiltin(BuiltinDeclaration* decl, std::string external_name, std::string readable_name, Signature signature, base::Optional<Statement*> body) { const bool javascript = decl->javascript_linkage; - const bool varargs = decl->signature->parameters.has_varargs; + const bool varargs = decl->parameters.has_varargs; Builtin::Kind kind = !javascript ? Builtin::kStub : varargs ? Builtin::kVarArgsJavaScript : Builtin::kFixedArgsJavaScript; @@ -82,6 +69,21 @@ Builtin* DeclarationVisitor::CreateBuiltin(BuiltinDeclaration* decl, " to be a JavaScript builtin"); } + if (javascript) { + if (!signature.return_type->IsSubtypeOf(TypeOracle::GetJSAnyType())) { + Error("Return type of JavaScript-linkage builtins has to be JSAny.") + .Position(decl->return_type->pos); + } + for (size_t i = signature.implicit_count; + i < signature.parameter_types.types.size(); ++i) { + const Type* parameter_type = signature.parameter_types.types[i]; + if (parameter_type != TypeOracle::GetJSAnyType()) { + Error("Parameters of JavaScript-linkage builtins have to be JSAny.") + .Position(decl->parameters.types[i]->pos); + } + } + } + for (size_t i = 0; i < signature.types().size(); ++i) { if (const StructType* type = StructType::DynamicCast(signature.types()[i])) { @@ -111,14 +113,20 @@ Builtin* DeclarationVisitor::CreateBuiltin(BuiltinDeclaration* decl, struct_type->name()); } - return Declarations::CreateBuiltin( - std::move(external_name), std::move(readable_name), kind, - std::move(signature), decl->transitioning, body); + return Declarations::CreateBuiltin(std::move(external_name), + std::move(readable_name), kind, + std::move(signature), body); +} + +void DeclarationVisitor::Visit(ExternalBuiltinDeclaration* decl) { + Declarations::Declare( + decl->name->value, + CreateBuiltin(decl, decl->name->value, decl->name->value, + TypeVisitor::MakeSignature(decl), base::nullopt)); } -void DeclarationVisitor::Visit(ExternalRuntimeDeclaration* decl, - const Signature& signature, - base::Optional<Statement*> body) { +void DeclarationVisitor::Visit(ExternalRuntimeDeclaration* decl) { + Signature signature = TypeVisitor::MakeSignature(decl); if (signature.parameter_types.types.size() == 0 || !(signature.parameter_types.types[0] == TypeOracle::GetContextType())) { ReportError( @@ -142,39 +150,34 @@ void DeclarationVisitor::Visit(ExternalRuntimeDeclaration* decl, } } - Declarations::DeclareRuntimeFunction(decl->name, signature, - decl->transitioning); + Declarations::DeclareRuntimeFunction(decl->name->value, signature); } -void DeclarationVisitor::Visit(ExternalMacroDeclaration* decl, - const Signature& signature, - base::Optional<Statement*> body) { - Declarations::DeclareMacro(decl->name, true, decl->external_assembler_name, - signature, decl->transitioning, body, decl->op); +void DeclarationVisitor::Visit(ExternalMacroDeclaration* decl) { + Declarations::DeclareMacro( + decl->name->value, true, decl->external_assembler_name, + TypeVisitor::MakeSignature(decl), base::nullopt, decl->op); } -void DeclarationVisitor::Visit(TorqueBuiltinDeclaration* decl, - const Signature& signature, - base::Optional<Statement*> body) { +void DeclarationVisitor::Visit(TorqueBuiltinDeclaration* decl) { Declarations::Declare( - decl->name, CreateBuiltin(decl, decl->name, decl->name, signature, body)); + decl->name->value, + CreateBuiltin(decl, decl->name->value, decl->name->value, + TypeVisitor::MakeSignature(decl), decl->body)); } -void DeclarationVisitor::Visit(TorqueMacroDeclaration* decl, - const Signature& signature, - base::Optional<Statement*> body) { +void DeclarationVisitor::Visit(TorqueMacroDeclaration* decl) { Macro* macro = Declarations::DeclareMacro( - decl->name, decl->export_to_csa, base::nullopt, signature, - decl->transitioning, body, decl->op); + decl->name->value, decl->export_to_csa, base::nullopt, + TypeVisitor::MakeSignature(decl), decl->body, decl->op); // TODO(szuend): Set identifier_position to decl->name->pos once all callable // names are changed from std::string to Identifier*. macro->SetPosition(decl->pos); } -void DeclarationVisitor::Visit(IntrinsicDeclaration* decl, - const Signature& signature, - base::Optional<Statement*> body) { - Declarations::DeclareIntrinsic(decl->name, signature); +void DeclarationVisitor::Visit(IntrinsicDeclaration* decl) { + Declarations::DeclareIntrinsic(decl->name->value, + TypeVisitor::MakeSignature(decl)); } void DeclarationVisitor::Visit(ConstDeclaration* decl) { @@ -182,30 +185,16 @@ void DeclarationVisitor::Visit(ConstDeclaration* decl) { decl->name, TypeVisitor::ComputeType(decl->type), decl->expression); } -void DeclarationVisitor::Visit(StandardDeclaration* decl) { - Signature signature = - TypeVisitor::MakeSignature(decl->callable->signature.get()); - Visit(decl->callable, signature, decl->body); -} - void DeclarationVisitor::Visit(SpecializationDeclaration* decl) { - if ((decl->body != nullptr) == decl->external) { - std::stringstream stream; - stream << "specialization of " << decl->name - << " must either be marked 'extern' or have a body"; - ReportError(stream.str()); - } - std::vector<Generic*> generic_list = Declarations::LookupGeneric(decl->name->value); // Find the matching generic specialization based on the concrete parameter // list. Generic* matching_generic = nullptr; - Signature signature_with_types = - TypeVisitor::MakeSignature(decl->signature.get()); + Signature signature_with_types = TypeVisitor::MakeSignature(decl); for (Generic* generic : generic_list) { Signature generic_signature_with_types = - MakeSpecializedSignature(SpecializationKey{ + MakeSpecializedSignature(SpecializationKey<Generic>{ generic, TypeVisitor::ComputeTypeVector(decl->generic_parameters)}); if (signature_with_types.HasSameTypesAs(generic_signature_with_types, ParameterMode::kIgnoreImplicit)) { @@ -233,7 +222,7 @@ void DeclarationVisitor::Visit(SpecializationDeclaration* decl) { stream << "\ncandidates are:"; for (Generic* generic : generic_list) { stream << "\n " - << MakeSpecializedSignature(SpecializationKey{ + << MakeSpecializedSignature(SpecializationKey<Generic>{ generic, TypeVisitor::ComputeTypeVector(decl->generic_parameters)}); } @@ -245,10 +234,12 @@ void DeclarationVisitor::Visit(SpecializationDeclaration* decl) { matching_generic->IdentifierPosition()); } - Specialize(SpecializationKey{matching_generic, TypeVisitor::ComputeTypeVector( - decl->generic_parameters)}, - matching_generic->declaration()->callable, decl->signature.get(), - decl->body, decl->pos); + CallableDeclaration* generic_declaration = matching_generic->declaration(); + + Specialize(SpecializationKey<Generic>{matching_generic, + TypeVisitor::ComputeTypeVector( + decl->generic_parameters)}, + generic_declaration, decl, decl->body, decl->pos); } void DeclarationVisitor::Visit(ExternConstDeclaration* decl) { @@ -267,10 +258,11 @@ void DeclarationVisitor::Visit(CppIncludeDeclaration* decl) { GlobalContext::AddCppInclude(decl->include_path); } -void DeclarationVisitor::DeclareSpecializedTypes(const SpecializationKey& key) { +void DeclarationVisitor::DeclareSpecializedTypes( + const SpecializationKey<Generic>& key) { size_t i = 0; const std::size_t generic_parameter_count = - key.generic->declaration()->generic_parameters.size(); + key.generic->generic_parameters().size(); if (generic_parameter_count != key.specialized_types.size()) { std::stringstream stream; stream << "Wrong generic argument count for specialization of \"" @@ -280,37 +272,35 @@ void DeclarationVisitor::DeclareSpecializedTypes(const SpecializationKey& key) { } for (auto type : key.specialized_types) { - Identifier* generic_type_name = - key.generic->declaration()->generic_parameters[i++]; + Identifier* generic_type_name = key.generic->generic_parameters()[i++]; TypeAlias* alias = Declarations::DeclareType(generic_type_name, type); alias->SetIsUserDefined(false); } } Signature DeclarationVisitor::MakeSpecializedSignature( - const SpecializationKey& key) { + const SpecializationKey<Generic>& key) { CurrentScope::Scope generic_scope(key.generic->ParentScope()); // Create a temporary fake-namespace just to temporarily declare the // specialization aliases for the generic types to create a signature. Namespace tmp_namespace("_tmp"); CurrentScope::Scope tmp_namespace_scope(&tmp_namespace); DeclareSpecializedTypes(key); - return TypeVisitor::MakeSignature( - key.generic->declaration()->callable->signature.get()); + return TypeVisitor::MakeSignature(key.generic->declaration()); } -Callable* DeclarationVisitor::SpecializeImplicit(const SpecializationKey& key) { - if (!key.generic->declaration()->body && - IntrinsicDeclaration::DynamicCast(key.generic->declaration()->callable) == - nullptr) { +Callable* DeclarationVisitor::SpecializeImplicit( + const SpecializationKey<Generic>& key) { + base::Optional<Statement*> body = key.generic->CallableBody(); + if (!body && IntrinsicDeclaration::DynamicCast(key.generic->declaration()) == + nullptr) { ReportError("missing specialization of ", key.generic->name(), " with types <", key.specialized_types, "> declared at ", key.generic->Position()); } CurrentScope::Scope generic_scope(key.generic->ParentScope()); - Callable* result = Specialize(key, key.generic->declaration()->callable, - base::nullopt, key.generic->declaration()->body, - CurrentSourcePosition::Get()); + Callable* result = Specialize(key, key.generic->declaration(), base::nullopt, + body, CurrentSourcePosition::Get()); result->SetIsUserDefined(false); CurrentScope::Scope callable_scope(result); DeclareSpecializedTypes(key); @@ -318,12 +308,11 @@ Callable* DeclarationVisitor::SpecializeImplicit(const SpecializationKey& key) { } Callable* DeclarationVisitor::Specialize( - const SpecializationKey& key, CallableNode* declaration, - base::Optional<const CallableNodeSignature*> signature, + const SpecializationKey<Generic>& key, CallableDeclaration* declaration, + base::Optional<const SpecializationDeclaration*> explicit_specialization, base::Optional<Statement*> body, SourcePosition position) { CurrentSourcePosition::Scope pos_scope(position); - size_t generic_parameter_count = - key.generic->declaration()->generic_parameters.size(); + size_t generic_parameter_count = key.generic->generic_parameters().size(); if (generic_parameter_count != key.specialized_types.size()) { std::stringstream stream; stream << "number of template parameters (" @@ -338,13 +327,15 @@ Callable* DeclarationVisitor::Specialize( " with types <", key.specialized_types, ">"); } - Signature type_signature = signature ? TypeVisitor::MakeSignature(*signature) - : MakeSpecializedSignature(key); + Signature type_signature = + explicit_specialization + ? TypeVisitor::MakeSignature(*explicit_specialization) + : MakeSpecializedSignature(key); std::string generated_name = Declarations::GetGeneratedCallableName( - declaration->name, key.specialized_types); + declaration->name->value, key.specialized_types); std::stringstream readable_name; - readable_name << declaration->name << "<"; + readable_name << declaration->name->value << "<"; bool first = true; for (const Type* t : key.specialized_types) { if (!first) readable_name << ", "; @@ -354,11 +345,12 @@ Callable* DeclarationVisitor::Specialize( readable_name << ">"; Callable* callable; if (MacroDeclaration::DynamicCast(declaration) != nullptr) { - callable = Declarations::CreateTorqueMacro( - generated_name, readable_name.str(), false, type_signature, - declaration->transitioning, *body, true); + callable = + Declarations::CreateTorqueMacro(generated_name, readable_name.str(), + false, type_signature, *body, true); } else if (IntrinsicDeclaration::DynamicCast(declaration) != nullptr) { - callable = Declarations::CreateIntrinsic(declaration->name, type_signature); + callable = + Declarations::CreateIntrinsic(declaration->name->value, type_signature); } else { BuiltinDeclaration* builtin = BuiltinDeclaration::cast(declaration); callable = CreateBuiltin(builtin, generated_name, readable_name.str(), diff --git a/deps/v8/src/torque/declaration-visitor.h b/deps/v8/src/torque/declaration-visitor.h index dbd28f4b87..3a5201e24a 100644 --- a/deps/v8/src/torque/declaration-visitor.h +++ b/deps/v8/src/torque/declaration-visitor.h @@ -45,7 +45,7 @@ class PredeclarationVisitor { } } static void Predeclare(GenericDeclaration* decl) { - Declarations::DeclareGeneric(decl->callable->name, decl); + Declarations::DeclareGeneric(decl->declaration->name->value, decl); } }; @@ -76,30 +76,15 @@ class DeclarationVisitor { 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)); - } - - 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); - static void Visit(CallableNode* decl, const Signature& signature, - base::Optional<Statement*> body); + static void Visit(ExternalBuiltinDeclaration* decl); + static void Visit(ExternalRuntimeDeclaration* decl); + static void Visit(ExternalMacroDeclaration* decl); + static void Visit(TorqueBuiltinDeclaration* decl); + static void Visit(TorqueMacroDeclaration* decl); + static void Visit(IntrinsicDeclaration* decl); static void Visit(ConstDeclaration* decl); - static void Visit(StandardDeclaration* decl); static void Visit(GenericDeclaration* decl) { // The PredeclarationVisitor already handled this case. } @@ -107,15 +92,16 @@ class DeclarationVisitor { static void Visit(ExternConstDeclaration* decl); static void Visit(CppIncludeDeclaration* decl); - static Signature MakeSpecializedSignature(const SpecializationKey& key); - static Callable* SpecializeImplicit(const SpecializationKey& key); + static Signature MakeSpecializedSignature( + const SpecializationKey<Generic>& key); + static Callable* SpecializeImplicit(const SpecializationKey<Generic>& key); static Callable* Specialize( - const SpecializationKey& key, CallableNode* declaration, - base::Optional<const CallableNodeSignature*> signature, + const SpecializationKey<Generic>& key, CallableDeclaration* declaration, + base::Optional<const SpecializationDeclaration*> explicit_specialization, base::Optional<Statement*> body, SourcePosition position); private: - static void DeclareSpecializedTypes(const SpecializationKey& key); + static void DeclareSpecializedTypes(const SpecializationKey<Generic>& key); }; } // namespace torque diff --git a/deps/v8/src/torque/declarations.cc b/deps/v8/src/torque/declarations.cc index 73d46d6998..ed4ad23044 100644 --- a/deps/v8/src/torque/declarations.cc +++ b/deps/v8/src/torque/declarations.cc @@ -11,9 +11,6 @@ namespace v8 { namespace internal { namespace torque { - -DEFINE_CONTEXTUAL_VARIABLE(GlobalContext) - namespace { template <class T> @@ -139,6 +136,13 @@ GenericStructType* Declarations::LookupUniqueGenericStructType( "generic struct"); } +base::Optional<GenericStructType*> Declarations::TryLookupGenericStructType( + const QualifiedName& name) { + std::vector<GenericStructType*> results = TryLookup<GenericStructType>(name); + if (results.empty()) return base::nullopt; + return EnsureUnique(results, name.name, "generic struct"); +} + Namespace* Declarations::DeclareNamespace(const std::string& name) { return Declare(name, std::unique_ptr<Namespace>(new Namespace(name))); } @@ -158,43 +162,44 @@ const TypeAlias* Declarations::PredeclareTypeAlias(const Identifier* name, return Declare(name->value, std::move(alias_ptr)); } -TorqueMacro* Declarations::CreateTorqueMacro( - std::string external_name, std::string readable_name, bool exported_to_csa, - Signature signature, bool transitioning, base::Optional<Statement*> body, - bool is_user_defined) { +TorqueMacro* Declarations::CreateTorqueMacro(std::string external_name, + std::string readable_name, + bool exported_to_csa, + Signature signature, + base::Optional<Statement*> body, + bool is_user_defined) { // TODO(tebbi): Switch to more predictable names to improve incremental // compilation. external_name += "_" + std::to_string(GlobalContext::FreshId()); return RegisterDeclarable(std::unique_ptr<TorqueMacro>(new TorqueMacro( std::move(external_name), std::move(readable_name), std::move(signature), - transitioning, body, is_user_defined, exported_to_csa))); + body, is_user_defined, exported_to_csa))); } ExternMacro* Declarations::CreateExternMacro( - std::string name, std::string external_assembler_name, Signature signature, - bool transitioning) { + std::string name, std::string external_assembler_name, + Signature signature) { return RegisterDeclarable(std::unique_ptr<ExternMacro>( new ExternMacro(std::move(name), std::move(external_assembler_name), - std::move(signature), transitioning))); + std::move(signature)))); } Macro* Declarations::DeclareMacro( const std::string& name, bool accessible_from_csa, base::Optional<std::string> external_assembler_name, - const Signature& signature, bool transitioning, - base::Optional<Statement*> body, base::Optional<std::string> op, - bool is_user_defined) { + const Signature& signature, base::Optional<Statement*> body, + base::Optional<std::string> op, bool is_user_defined) { if (TryLookupMacro(name, signature.GetExplicitTypes())) { ReportError("cannot redeclare macro ", name, " with identical explicit parameters"); } Macro* macro; if (external_assembler_name) { - macro = CreateExternMacro(name, std::move(*external_assembler_name), - signature, transitioning); + macro = + CreateExternMacro(name, std::move(*external_assembler_name), signature); } else { - macro = CreateTorqueMacro(name, name, accessible_from_csa, signature, - transitioning, body, is_user_defined); + macro = CreateTorqueMacro(name, name, accessible_from_csa, signature, body, + is_user_defined); } Declare(name, macro); if (op) { @@ -209,11 +214,11 @@ Macro* Declarations::DeclareMacro( Method* Declarations::CreateMethod(AggregateType* container_type, const std::string& name, Signature signature, - bool transitioning, Statement* body) { + Statement* body) { std::string generated_name{container_type->GetGeneratedMethodName(name)}; Method* result = RegisterDeclarable(std::unique_ptr<Method>( new Method(container_type, container_type->GetGeneratedMethodName(name), - name, std::move(signature), transitioning, body))); + name, std::move(signature), body))); container_type->RegisterMethod(result); return result; } @@ -235,29 +240,27 @@ Intrinsic* Declarations::DeclareIntrinsic(const std::string& name, Builtin* Declarations::CreateBuiltin(std::string external_name, std::string readable_name, Builtin::Kind kind, Signature signature, - bool transitioning, + base::Optional<Statement*> body) { return RegisterDeclarable(std::unique_ptr<Builtin>( new Builtin(std::move(external_name), std::move(readable_name), kind, - std::move(signature), transitioning, body))); + std::move(signature), body))); } Builtin* Declarations::DeclareBuiltin(const std::string& name, Builtin::Kind kind, const Signature& signature, - bool transitioning, + base::Optional<Statement*> body) { CheckAlreadyDeclared<Builtin>(name, "builtin"); - return Declare( - name, CreateBuiltin(name, name, kind, signature, transitioning, body)); + return Declare(name, CreateBuiltin(name, name, kind, signature, body)); } RuntimeFunction* Declarations::DeclareRuntimeFunction( - const std::string& name, const Signature& signature, bool transitioning) { + const std::string& name, const Signature& signature) { CheckAlreadyDeclared<RuntimeFunction>(name, "runtime function"); - return Declare(name, - RegisterDeclarable(std::unique_ptr<RuntimeFunction>( - new RuntimeFunction(name, signature, transitioning)))); + return Declare(name, RegisterDeclarable(std::unique_ptr<RuntimeFunction>( + new RuntimeFunction(name, signature)))); } void Declarations::DeclareExternConstant(Identifier* name, const Type* type, diff --git a/deps/v8/src/torque/declarations.h b/deps/v8/src/torque/declarations.h index 00e0facefe..240680fa1e 100644 --- a/deps/v8/src/torque/declarations.h +++ b/deps/v8/src/torque/declarations.h @@ -15,8 +15,6 @@ namespace internal { namespace torque { static constexpr const char* const kFromConstexprMacroName = "FromConstexpr"; -static constexpr const char* kTrueLabelName = "__True"; -static constexpr const char* kFalseLabelName = "__False"; static constexpr const char* kMacroEndLabelName = "__macro_end"; static constexpr const char* kBreakLabelName = "__break"; static constexpr const char* kContinueLabelName = "__continue"; @@ -78,6 +76,8 @@ class Declarations { static GenericStructType* LookupUniqueGenericStructType( const QualifiedName& name); + static base::Optional<GenericStructType*> TryLookupGenericStructType( + const QualifiedName& name); static Namespace* DeclareNamespace(const std::string& name); static TypeAlias* DeclareType(const Identifier* name, const Type* type); @@ -88,23 +88,21 @@ class Declarations { static TorqueMacro* CreateTorqueMacro(std::string external_name, std::string readable_name, bool exported_to_csa, - Signature signature, bool transitioning, + Signature signature, base::Optional<Statement*> body, bool is_user_defined); static ExternMacro* CreateExternMacro(std::string name, std::string external_assembler_name, - Signature signature, - bool transitioning); + Signature signature); static Macro* DeclareMacro( const std::string& name, bool accessible_from_csa, base::Optional<std::string> external_assembler_name, - const Signature& signature, bool transitioning, - base::Optional<Statement*> body, base::Optional<std::string> op = {}, - bool is_user_defined = true); + const Signature& signature, base::Optional<Statement*> body, + base::Optional<std::string> op = {}, bool is_user_defined = true); static Method* CreateMethod(AggregateType* class_type, const std::string& name, Signature signature, - bool transitioning, Statement* body); + Statement* body); static Intrinsic* CreateIntrinsic(const std::string& name, const Signature& signature); @@ -114,15 +112,14 @@ class Declarations { static Builtin* CreateBuiltin(std::string external_name, std::string readable_name, Builtin::Kind kind, - Signature signature, bool transitioning, + Signature signature, base::Optional<Statement*> body); static Builtin* DeclareBuiltin(const std::string& name, Builtin::Kind kind, - const Signature& signature, bool transitioning, + const Signature& signature, base::Optional<Statement*> body); static RuntimeFunction* DeclareRuntimeFunction(const std::string& name, - const Signature& signature, - bool transitioning); + const Signature& signature); static void DeclareExternConstant(Identifier* name, const Type* type, std::string value); diff --git a/deps/v8/src/torque/earley-parser.h b/deps/v8/src/torque/earley-parser.h index d3d0c89c42..9f7ba6a7ae 100644 --- a/deps/v8/src/torque/earley-parser.h +++ b/deps/v8/src/torque/earley-parser.h @@ -56,8 +56,8 @@ enum class ParseResultHolderBase::TypeId { kImplicitParameters, kOptionalImplicitParameters, kNameAndExpression, - kConditionalAnnotation, - kOptionalConditionalAnnotation, + kAnnotation, + kVectorOfAnnotation, kClassFieldExpression, kStructFieldExpression, kStdVectorOfNameAndTypeExpression, diff --git a/deps/v8/src/torque/global-context.cc b/deps/v8/src/torque/global-context.cc index f258f18474..13503038c5 100644 --- a/deps/v8/src/torque/global-context.cc +++ b/deps/v8/src/torque/global-context.cc @@ -8,6 +8,9 @@ namespace v8 { namespace internal { namespace torque { +DEFINE_CONTEXTUAL_VARIABLE(GlobalContext) +DEFINE_CONTEXTUAL_VARIABLE(TargetArchitecture) + GlobalContext::GlobalContext(Ast ast) : collect_language_server_data_(false), force_assert_statements_(false), @@ -19,6 +22,10 @@ GlobalContext::GlobalContext(Ast ast) RegisterDeclarable(base::make_unique<Namespace>(kBaseNamespaceName)); } +TargetArchitecture::TargetArchitecture(bool force_32bit) + : tagged_size_(force_32bit ? sizeof(int32_t) : kTaggedSize), + raw_ptr_size_(force_32bit ? sizeof(int32_t) : kSystemPointerSize) {} + } // namespace torque } // namespace internal } // namespace v8 diff --git a/deps/v8/src/torque/global-context.h b/deps/v8/src/torque/global-context.h index e103a22575..e1106adbd1 100644 --- a/deps/v8/src/torque/global-context.h +++ b/deps/v8/src/torque/global-context.h @@ -7,6 +7,7 @@ #include <map> +#include "src/common/globals.h" #include "src/torque/ast.h" #include "src/torque/contextual.h" #include "src/torque/declarable.h" @@ -91,6 +92,18 @@ T* RegisterDeclarable(std::unique_ptr<T> d) { return GlobalContext::Get().RegisterDeclarable(std::move(d)); } +class TargetArchitecture : public ContextualClass<TargetArchitecture> { + public: + explicit TargetArchitecture(bool force_32bit); + + static int TaggedSize() { return Get().tagged_size_; } + static int RawPtrSize() { return Get().raw_ptr_size_; } + + private: + const int tagged_size_; + const int raw_ptr_size_; +}; + } // namespace torque } // namespace internal } // namespace v8 diff --git a/deps/v8/src/torque/implementation-visitor.cc b/deps/v8/src/torque/implementation-visitor.cc index a0aeeee81b..8f36afd020 100644 --- a/deps/v8/src/torque/implementation-visitor.cc +++ b/deps/v8/src/torque/implementation-visitor.cc @@ -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-inference.h" #include "src/torque/type-visitor.h" namespace v8 { @@ -107,7 +108,8 @@ void ImplementationVisitor::EndCSAFiles() { } void ImplementationVisitor::Visit(NamespaceConstant* decl) { - Signature signature{{}, base::nullopt, {{}, false}, 0, decl->type(), {}}; + Signature signature{{}, base::nullopt, {{}, false}, 0, decl->type(), + {}, false}; BindingsManagersScope bindings_managers_scope; @@ -466,13 +468,13 @@ void ImplementationVisitor::Visit(Builtin* builtin) { : "UncheckedCast<Object>(Parameter(Descriptor::kReceiver))") << ";\n"; source_out() << "USE(" << generated_name << ");\n"; - expected_type = TypeOracle::GetObjectType(); + expected_type = TypeOracle::GetJSAnyType(); } else if (param_name == "newTarget") { source_out() << " TNode<Object> " << generated_name << " = UncheckedCast<Object>(Parameter(" << "Descriptor::kJSNewTarget));\n"; source_out() << "USE(" << generated_name << ");\n"; - expected_type = TypeOracle::GetObjectType(); + expected_type = TypeOracle::GetJSAnyType(); } else if (param_name == "target") { source_out() << " TNode<JSFunction> " << generated_name << " = UncheckedCast<JSFunction>(Parameter(" @@ -646,24 +648,8 @@ VisitResult ImplementationVisitor::Visit(ConditionalExpression* expr) { } VisitResult ImplementationVisitor::Visit(LogicalOrExpression* expr) { - VisitResult left_result; - { - Block* false_block = assembler().NewBlock(assembler().CurrentStack()); - Binding<LocalLabel> false_binding{&LabelBindingsManager::Get(), - kFalseLabelName, LocalLabel{false_block}}; - left_result = Visit(expr->left); - if (left_result.type()->IsBool()) { - Block* true_block = LookupSimpleLabel(kTrueLabelName); - assembler().Branch(true_block, false_block); - assembler().Bind(false_block); - } else if (left_result.type()->IsNever()) { - assembler().Bind(false_block); - } else if (!left_result.type()->IsConstexprBool()) { - ReportError( - "expected type bool, constexpr bool, or never on left-hand side of " - "operator ||"); - } - } + StackScope outer_scope(this); + VisitResult left_result = Visit(expr->left); if (left_result.type()->IsConstexprBool()) { VisitResult right_result = Visit(expr->right); @@ -677,38 +663,34 @@ VisitResult ImplementationVisitor::Visit(LogicalOrExpression* expr) { " || " + right_result.constexpr_value() + ")"); } - VisitResult right_result = Visit(expr->right); - if (right_result.type()->IsBool()) { - Block* true_block = LookupSimpleLabel(kTrueLabelName); - Block* false_block = LookupSimpleLabel(kFalseLabelName); - assembler().Branch(true_block, false_block); - return VisitResult::NeverResult(); - } else if (!right_result.type()->IsNever()) { - ReportError( - "expected type bool or never on right-hand side of operator ||"); + Block* true_block = assembler().NewBlock(); + Block* false_block = assembler().NewBlock(); + Block* done_block = assembler().NewBlock(); + + left_result = GenerateImplicitConvert(TypeOracle::GetBoolType(), left_result); + GenerateBranch(left_result, true_block, false_block); + + assembler().Bind(true_block); + VisitResult true_result = GenerateBoolConstant(true); + assembler().Goto(done_block); + + assembler().Bind(false_block); + VisitResult false_result; + { + StackScope false_block_scope(this); + false_result = false_block_scope.Yield( + GenerateImplicitConvert(TypeOracle::GetBoolType(), Visit(expr->right))); } - return right_result; + assembler().Goto(done_block); + + assembler().Bind(done_block); + DCHECK_EQ(true_result, false_result); + return outer_scope.Yield(true_result); } VisitResult ImplementationVisitor::Visit(LogicalAndExpression* expr) { - VisitResult left_result; - { - Block* true_block = assembler().NewBlock(assembler().CurrentStack()); - Binding<LocalLabel> false_binding{&LabelBindingsManager::Get(), - kTrueLabelName, LocalLabel{true_block}}; - left_result = Visit(expr->left); - if (left_result.type()->IsBool()) { - Block* false_block = LookupSimpleLabel(kFalseLabelName); - assembler().Branch(true_block, false_block); - assembler().Bind(true_block); - } else if (left_result.type()->IsNever()) { - assembler().Bind(true_block); - } else if (!left_result.type()->IsConstexprBool()) { - ReportError( - "expected type bool, constexpr bool, or never on left-hand side of " - "operator &&"); - } - } + StackScope outer_scope(this); + VisitResult left_result = Visit(expr->left); if (left_result.type()->IsConstexprBool()) { VisitResult right_result = Visit(expr->right); @@ -722,17 +704,29 @@ VisitResult ImplementationVisitor::Visit(LogicalAndExpression* expr) { " && " + right_result.constexpr_value() + ")"); } - VisitResult right_result = Visit(expr->right); - if (right_result.type()->IsBool()) { - Block* true_block = LookupSimpleLabel(kTrueLabelName); - Block* false_block = LookupSimpleLabel(kFalseLabelName); - assembler().Branch(true_block, false_block); - return VisitResult::NeverResult(); - } else if (!right_result.type()->IsNever()) { - ReportError( - "expected type bool or never on right-hand side of operator &&"); + Block* true_block = assembler().NewBlock(); + Block* false_block = assembler().NewBlock(); + Block* done_block = assembler().NewBlock(); + + left_result = GenerateImplicitConvert(TypeOracle::GetBoolType(), left_result); + GenerateBranch(left_result, true_block, false_block); + + assembler().Bind(true_block); + VisitResult true_result; + { + StackScope true_block_scope(this); + true_result = true_block_scope.Yield( + GenerateImplicitConvert(TypeOracle::GetBoolType(), Visit(expr->right))); } - return right_result; + assembler().Goto(done_block); + + assembler().Bind(false_block); + VisitResult false_result = GenerateBoolConstant(false); + assembler().Goto(done_block); + + assembler().Bind(done_block); + DCHECK_EQ(true_result, false_result); + return outer_scope.Yield(true_result); } VisitResult ImplementationVisitor::Visit(IncrementDecrementExpression* expr) { @@ -1110,29 +1104,6 @@ const Type* ImplementationVisitor::Visit(ReturnStatement* stmt) { return TypeOracle::GetNeverType(); } -VisitResult ImplementationVisitor::TemporaryUninitializedStruct( - const StructType* struct_type, const std::string& reason) { - StackRange range = assembler().TopRange(0); - for (const Field& f : struct_type->fields()) { - if (const StructType* struct_type = - StructType::DynamicCast(f.name_and_type.type)) { - range.Extend( - TemporaryUninitializedStruct(struct_type, reason).stack_range()); - } else { - std::string descriptor = "uninitialized field '" + f.name_and_type.name + - "' declared at " + PositionAsString(f.pos) + - " (" + reason + ")"; - TypeVector lowered_types = LowerType(f.name_and_type.type); - for (const Type* type : lowered_types) { - assembler().Emit(PushUninitializedInstruction{ - TypeOracle::GetTopType(descriptor, type)}); - } - range.Extend(assembler().TopRange(lowered_types.size())); - } - } - return VisitResult(struct_type, range); -} - VisitResult ImplementationVisitor::Visit(TryLabelExpression* expr) { size_t parameter_count = expr->label_block->parameters.names.size(); std::vector<VisitResult> parameters; @@ -1211,15 +1182,38 @@ VisitResult ImplementationVisitor::Visit(StatementExpression* expr) { return VisitResult{Visit(expr->statement), assembler().TopRange(0)}; } +void ImplementationVisitor::CheckInitializersWellformed( + const std::string& aggregate_name, + const std::vector<Field>& aggregate_fields, + const std::vector<NameAndExpression>& initializers, + bool ignore_first_field) { + size_t fields_offset = ignore_first_field ? 1 : 0; + size_t fields_size = aggregate_fields.size() - fields_offset; + for (size_t i = 0; i < std::min(fields_size, initializers.size()); i++) { + const std::string& field_name = + aggregate_fields[i + fields_offset].name_and_type.name; + Identifier* found_name = initializers[i].name; + if (field_name != found_name->value) { + Error("Expected field name \"", field_name, "\" instead of \"", + found_name->value, "\"") + .Position(found_name->pos) + .Throw(); + } + } + if (fields_size != initializers.size()) { + ReportError("expected ", fields_size, " initializers for ", aggregate_name, + " found ", initializers.size()); + } +} + InitializerResults ImplementationVisitor::VisitInitializerResults( - const AggregateType* current_aggregate, + const ClassType* class_type, const std::vector<NameAndExpression>& initializers) { InitializerResults result; for (const NameAndExpression& initializer : initializers) { result.names.push_back(initializer.name); Expression* e = initializer.expression; - const Field& field = - current_aggregate->LookupField(initializer.name->value); + const Field& field = class_type->LookupField(initializer.name->value); auto field_index = field.index; if (SpreadExpression* s = SpreadExpression::DynamicCast(e)) { if (!field_index) { @@ -1238,54 +1232,30 @@ InitializerResults ImplementationVisitor::VisitInitializerResults( return result; } -size_t ImplementationVisitor::InitializeAggregateHelper( - const AggregateType* aggregate_type, VisitResult allocate_result, +void ImplementationVisitor::InitializeClass( + const ClassType* class_type, VisitResult allocate_result, const InitializerResults& initializer_results) { - const ClassType* current_class = ClassType::DynamicCast(aggregate_type); - size_t current = 0; - if (current_class) { - const ClassType* super = current_class->GetSuperClass(); - if (super) { - current = InitializeAggregateHelper(super, allocate_result, - initializer_results); - } + if (const ClassType* super = class_type->GetSuperClass()) { + InitializeClass(super, allocate_result, initializer_results); } - for (Field f : aggregate_type->fields()) { - if (current == initializer_results.field_value_map.size()) { - ReportError("insufficient number of initializers for ", - aggregate_type->name()); - } + for (Field f : class_type->fields()) { VisitResult current_value = initializer_results.field_value_map.at(f.name_and_type.name); - Identifier* fieldname = initializer_results.names[current]; - if (fieldname->value != f.name_and_type.name) { - CurrentSourcePosition::Scope scope(fieldname->pos); - ReportError("Expected fieldname \"", f.name_and_type.name, - "\" instead of \"", fieldname->value, "\""); - } - if (aggregate_type->IsClassType()) { - if (f.index) { - InitializeFieldFromSpread(allocate_result, f, initializer_results); - } else { - allocate_result.SetType(aggregate_type); - GenerateCopy(allocate_result); - assembler().Emit(CreateFieldReferenceInstruction{ - ClassType::cast(aggregate_type), f.name_and_type.name}); - VisitResult heap_reference( - TypeOracle::GetReferenceType(f.name_and_type.type), - assembler().TopRange(2)); - GenerateAssignToLocation( - LocationReference::HeapReference(heap_reference), current_value); - } + if (f.index) { + InitializeFieldFromSpread(allocate_result, f, initializer_results); } else { - LocationReference struct_field_ref = LocationReference::VariableAccess( - ProjectStructField(allocate_result, f.name_and_type.name)); - GenerateAssignToLocation(struct_field_ref, current_value); + allocate_result.SetType(class_type); + GenerateCopy(allocate_result); + assembler().Emit(CreateFieldReferenceInstruction{ + ClassType::cast(class_type), f.name_and_type.name}); + VisitResult heap_reference( + TypeOracle::GetReferenceType(f.name_and_type.type), + assembler().TopRange(2)); + GenerateAssignToLocation(LocationReference::HeapReference(heap_reference), + current_value); } - ++current; } - return current; } void ImplementationVisitor::InitializeFieldFromSpread( @@ -1304,17 +1274,6 @@ void ImplementationVisitor::InitializeFieldFromSpread( {field.aggregate, index.type, iterator.type()}); } -void ImplementationVisitor::InitializeAggregate( - const AggregateType* aggregate_type, VisitResult allocate_result, - const InitializerResults& initializer_results) { - size_t consumed_initializers = InitializeAggregateHelper( - aggregate_type, allocate_result, initializer_results); - if (consumed_initializers != initializer_results.field_value_map.size()) { - ReportError("more initializers than fields present in ", - aggregate_type->name()); - } -} - VisitResult ImplementationVisitor::AddVariableObjectSize( VisitResult object_size, const ClassType* current_class, const InitializerResults& initializer_results) { @@ -1397,6 +1356,11 @@ VisitResult ImplementationVisitor::Visit(NewExpression* expr) { initializer_results.field_value_map[map_field.name_and_type.name] = object_map; } + + CheckInitializersWellformed(class_type->name(), + class_type->ComputeAllFields(), + expr->initializers, !class_type->IsExtern()); + Arguments size_arguments; size_arguments.parameters.push_back(object_map); VisitResult object_size = GenerateCall("%GetAllocationBaseSize", @@ -1411,7 +1375,7 @@ VisitResult ImplementationVisitor::Visit(NewExpression* expr) { GenerateCall("%Allocate", allocate_arguments, {class_type}, false); DCHECK(allocate_result.IsOnStack()); - InitializeAggregate(class_type, allocate_result, initializer_results); + InitializeClass(class_type, allocate_result, initializer_results); return stack_scope.Yield(allocate_result); } @@ -1582,7 +1546,9 @@ namespace { void FailCallableLookup(const std::string& reason, const QualifiedName& name, const TypeVector& parameter_types, const std::vector<Binding<LocalLabel>*>& labels, - const std::vector<Signature>& candidates) { + const std::vector<Signature>& candidates, + const std::vector<std::tuple<Generic*, const char*>> + inapplicable_generics) { std::stringstream stream; stream << "\n" << reason << ": \n " << name << "(" << parameter_types << ")"; if (labels.size() != 0) { @@ -1596,10 +1562,20 @@ void FailCallableLookup(const std::string& reason, const QualifiedName& name, stream << "\n " << name; PrintSignature(stream, signature, false); } + if (inapplicable_generics.size() != 0) { + stream << "\nfailed to instantiate all of these generic declarations:"; + for (auto& failure : inapplicable_generics) { + Generic* generic; + const char* reason; + std::tie(generic, reason) = failure; + stream << "\n " << generic->name() << " defined at " + << generic->Position() << ":\n " << reason << "\n"; + } + } ReportError(stream.str()); } -Callable* GetOrCreateSpecialization(const SpecializationKey& key) { +Callable* GetOrCreateSpecialization(const SpecializationKey<Generic>& key) { if (base::Optional<Callable*> specialization = key.generic->specializations().Get(key.specialized_types)) { return *specialization; @@ -1655,16 +1631,20 @@ Callable* ImplementationVisitor::LookupCallable( std::vector<Declarable*> overloads; std::vector<Signature> overload_signatures; + std::vector<std::tuple<Generic*, const char*>> inapplicable_generics; for (auto* declarable : declaration_container) { if (Generic* generic = Generic::DynamicCast(declarable)) { - base::Optional<TypeVector> inferred_specialization_types = - generic->InferSpecializationTypes(specialization_types, - parameter_types); - if (!inferred_specialization_types) continue; + TypeArgumentInference inference = generic->InferSpecializationTypes( + specialization_types, parameter_types); + if (inference.HasFailed()) { + inapplicable_generics.push_back( + std::make_tuple(generic, inference.GetFailureReason())); + continue; + } overloads.push_back(generic); overload_signatures.push_back( DeclarationVisitor::MakeSpecializedSignature( - SpecializationKey{generic, *inferred_specialization_types})); + SpecializationKey<Generic>{generic, inference.GetResult()})); } else if (Callable* callable = Callable::DynamicCast(declarable)) { overloads.push_back(callable); overload_signatures.push_back(callable->signature()); @@ -1674,16 +1654,12 @@ Callable* ImplementationVisitor::LookupCallable( std::vector<size_t> candidates; for (size_t i = 0; i < overloads.size(); ++i) { const Signature& signature = overload_signatures[i]; - bool try_bool_context = labels.size() == 0 && - signature.return_type == TypeOracle::GetNeverType(); - if (IsCompatibleSignature(signature, parameter_types, labels.size()) || - (try_bool_context && - IsCompatibleSignature(signature, parameter_types, 2))) { + if (IsCompatibleSignature(signature, parameter_types, labels.size())) { candidates.push_back(i); } } - if (overloads.empty()) { + if (overloads.empty() && inapplicable_generics.empty()) { if (silence_errors) return nullptr; std::stringstream stream; stream << "no matching declaration found for " << name; @@ -1691,7 +1667,8 @@ Callable* ImplementationVisitor::LookupCallable( } else if (candidates.empty()) { if (silence_errors) return nullptr; FailCallableLookup("cannot find suitable callable with name", name, - parameter_types, labels, overload_signatures); + parameter_types, labels, overload_signatures, + inapplicable_generics); } auto is_better_candidate = [&](size_t a, size_t b) { @@ -1712,14 +1689,15 @@ Callable* ImplementationVisitor::LookupCallable( candidate_signatures.push_back(overload_signatures[i]); } FailCallableLookup("ambiguous callable ", name, parameter_types, labels, - candidate_signatures); + candidate_signatures, inapplicable_generics); } } if (Generic* generic = Generic::DynamicCast(overloads[best])) { + TypeArgumentInference inference = generic->InferSpecializationTypes( + specialization_types, parameter_types); result = GetOrCreateSpecialization( - SpecializationKey{generic, *generic->InferSpecializationTypes( - specialization_types, parameter_types)}); + SpecializationKey<Generic>{generic, inference.GetResult()}); } else { result = Callable::cast(overloads[best]); } @@ -1749,14 +1727,13 @@ Callable* ImplementationVisitor::LookupCallable( } Method* ImplementationVisitor::LookupMethod( - const std::string& name, LocationReference this_reference, + const std::string& name, const AggregateType* receiver_type, const Arguments& arguments, const TypeVector& specialization_types) { TypeVector types(arguments.parameters.ComputeTypeVector()); - types.insert(types.begin(), this_reference.ReferencedType()); - return Method::cast(LookupCallable( - {{}, name}, - AggregateType::cast(this_reference.ReferencedType())->Methods(name), - types, arguments.labels, specialization_types)); + types.insert(types.begin(), receiver_type); + return Method::cast(LookupCallable({{}, name}, receiver_type->Methods(name), + types, arguments.labels, + specialization_types)); } const Type* ImplementationVisitor::GetCommonType(const Type* left, @@ -1783,24 +1760,36 @@ VisitResult ImplementationVisitor::GenerateCopy(const VisitResult& to_copy) { VisitResult ImplementationVisitor::Visit(StructExpression* expr) { StackScope stack_scope(this); - const Type* raw_type = TypeVisitor::ComputeType(expr->type); - if (!raw_type->IsStructType()) { - ReportError(*raw_type, " is not a struct but used like one"); - } - const StructType* struct_type = StructType::cast(raw_type); + auto& initializers = expr->initializers; + std::vector<VisitResult> values; + std::vector<const Type*> term_argument_types; + values.reserve(initializers.size()); + term_argument_types.reserve(initializers.size()); - InitializerResults initialization_results = - ImplementationVisitor::VisitInitializerResults(struct_type, - expr->initializers); + // Compute values and types of all initializer arguments + for (const NameAndExpression& initializer : initializers) { + VisitResult value = Visit(initializer.expression); + values.push_back(value); + term_argument_types.push_back(value.type()); + } - // Push uninitialized 'this' - VisitResult result = TemporaryUninitializedStruct( - struct_type, "it's not initialized in the struct " + struct_type->name()); + // Compute and check struct type from given struct name and argument types + const StructType* struct_type = TypeVisitor::ComputeTypeForStructExpression( + expr->type, term_argument_types); + CheckInitializersWellformed(struct_type->name(), struct_type->fields(), + initializers); - InitializeAggregate(struct_type, result, initialization_results); + // Implicitly convert values and thereby build the struct on the stack + StackRange struct_range = assembler().TopRange(0); + auto& fields = struct_type->fields(); + for (size_t i = 0; i < values.size(); i++) { + values[i] = + GenerateImplicitConvert(fields[i].name_and_type.type, values[i]); + struct_range.Extend(values[i].stack_range()); + } - return stack_scope.Yield(result); + return stack_scope.Yield(VisitResult(struct_type, struct_range)); } LocationReference ImplementationVisitor::GetLocationReference( @@ -1865,7 +1854,33 @@ LocationReference ImplementationVisitor::GetLocationReference( LanguageServerData::AddDefinition(expr->field->pos, field.pos); } if (field.index) { - return LocationReference::IndexedFieldAccess(object_result, fieldname); + assembler().Emit( + CreateFieldReferenceInstruction{object_result.type(), fieldname}); + // Fetch the length from the object + { + StackScope length_scope(this); + // Get a reference to the length + const Field* index_field = field.index.value(); + GenerateCopy(object_result); + assembler().Emit(CreateFieldReferenceInstruction{ + object_result.type(), index_field->name_and_type.name}); + VisitResult length_reference( + TypeOracle::GetReferenceType(index_field->name_and_type.type), + assembler().TopRange(2)); + + // Load the length from the reference and convert it to intptr + VisitResult length = GenerateFetchFromLocation( + LocationReference::HeapReference(length_reference)); + VisitResult converted_length = + GenerateCall("Convert", {{length}, {}}, + {TypeOracle::GetIntPtrType(), length.type()}, false); + DCHECK_EQ(converted_length.stack_range().Size(), 1); + length_scope.Yield(converted_length); + } + const Type* slice_type = + TypeOracle::GetSliceType(field.name_and_type.type); + return LocationReference::HeapSlice( + VisitResult(slice_type, assembler().TopRange(3))); } else { assembler().Emit( CreateFieldReferenceInstruction{*class_type, fieldname}); @@ -1883,8 +1898,13 @@ LocationReference ImplementationVisitor::GetLocationReference( ElementAccessExpression* expr) { LocationReference reference = GetLocationReference(expr->array); VisitResult index = Visit(expr->index); - if (reference.IsIndexedFieldAccess()) { - return LocationReference::IndexedFieldIndexedAccess(reference, index); + if (reference.IsHeapSlice()) { + Arguments arguments{{index}, {}}; + const AggregateType* slice_type = + AggregateType::cast(reference.heap_slice().type()); + Method* method = LookupMethod("AtIndex", slice_type, arguments, {}); + return LocationReference::HeapReference( + GenerateCall(method, reference, arguments, {}, false)); } else { return LocationReference::ArrayAccess(GenerateFetchFromLocation(reference), index); @@ -1927,8 +1947,9 @@ LocationReference ImplementationVisitor::GetLocationReference( } if (expr->generic_arguments.size() != 0) { Generic* generic = Declarations::LookupUniqueGeneric(name); - Callable* specialization = GetOrCreateSpecialization(SpecializationKey{ - generic, TypeVisitor::ComputeTypeVector(expr->generic_arguments)}); + Callable* specialization = + GetOrCreateSpecialization(SpecializationKey<Generic>{ + generic, TypeVisitor::ComputeTypeVector(expr->generic_arguments)}); if (Builtin* builtin = Builtin::DynamicCast(specialization)) { DCHECK(!builtin->IsExternal()); return LocationReference::Temporary(GetBuiltinCode(builtin), @@ -1963,8 +1984,8 @@ LocationReference ImplementationVisitor::GetLocationReference( LocationReference ImplementationVisitor::GetLocationReference( DereferenceExpression* expr) { VisitResult ref = Visit(expr->reference); - const ReferenceType* type = ReferenceType::DynamicCast(ref.type()); - if (!type) { + if (!StructType::MatchUnaryGeneric(ref.type(), + TypeOracle::GetReferenceGeneric())) { ReportError("Operator * expects a reference but found a value of type ", *ref.type()); } @@ -1983,7 +2004,7 @@ VisitResult ImplementationVisitor::GenerateFetchFromLocation( DCHECK_EQ(1, LoweredSlotCount(reference.ReferencedType())); return VisitResult(reference.ReferencedType(), assembler().TopRange(1)); } else { - if (reference.IsIndexedFieldAccess()) { + if (reference.IsHeapSlice()) { ReportError( "fetching a value directly from an indexed field isn't allowed"); } @@ -2011,12 +2032,19 @@ void ImplementationVisitor::GenerateAssignToLocation( if (reference.binding()) { (*reference.binding())->SetWritten(); } - } else if (reference.IsIndexedFieldAccess()) { + } else if (reference.IsHeapSlice()) { ReportError("assigning a value directly to an indexed field isn't allowed"); } else if (reference.IsHeapReference()) { const Type* referenced_type = reference.ReferencedType(); GenerateCopy(reference.heap_reference()); - GenerateImplicitConvert(referenced_type, assignment_value); + VisitResult converted_assignment_value = + GenerateImplicitConvert(referenced_type, assignment_value); + if (referenced_type == TypeOracle::GetFloat64Type()) { + VisitResult silenced_float_value = + GenerateCall("Float64SilenceNaN", {{assignment_value}, {}}); + assembler().Poke(converted_assignment_value.stack_range(), + silenced_float_value.stack_range(), referenced_type); + } assembler().Emit(StoreReferenceInstruction{referenced_type}); } else { DCHECK(reference.IsTemporary()); @@ -2097,27 +2125,20 @@ VisitResult ImplementationVisitor::GenerateCall( Callable* callable, base::Optional<LocationReference> this_reference, Arguments arguments, const TypeVector& specialization_types, bool is_tailcall) { - // Operators used in a branching context can also be function calls that never - // return but have a True and False label - if (arguments.labels.size() == 0 && - callable->signature().labels.size() == 2) { - base::Optional<Binding<LocalLabel>*> true_label = - TryLookupLabel(kTrueLabelName); - base::Optional<Binding<LocalLabel>*> false_label = - TryLookupLabel(kFalseLabelName); - if (!true_label || !false_label) { - ReportError( - callable->ReadableName(), - " does not return a value, but has to be called in a branching " - "context (e.g., conditional or if-condition). You can fix this by " - "adding \"? true : false\"."); + const Type* return_type = callable->signature().return_type; + + if (is_tailcall) { + if (Builtin* builtin = Builtin::DynamicCast(CurrentCallable::Get())) { + const Type* outer_return_type = builtin->signature().return_type; + if (!return_type->IsSubtypeOf(outer_return_type)) { + Error("Cannot tailcall, type of result is ", *return_type, + " but should be a subtype of ", *outer_return_type, "."); + } + } else { + Error("Tail calls are only allowed from builtins"); } - arguments.labels.push_back(*true_label); - arguments.labels.push_back(*false_label); } - const Type* return_type = callable->signature().return_type; - std::vector<VisitResult> converted_arguments; StackRange argument_range = assembler().TopRange(0); std::vector<std::string> constexpr_arguments; @@ -2142,8 +2163,8 @@ VisitResult ImplementationVisitor::GenerateCall( if (this_reference) { DCHECK(callable->IsMethod()); Method* method = Method::cast(callable); - // By now, the this reference should either be a variable or - // a temporary, in both cases the fetch of the VisitResult should succeed. + // By now, the this reference should either be a variable, a temporary or + // a Slice. In either case the fetch of the VisitResult should succeed. VisitResult this_value = this_reference->GetVisitResult(); if (method->ShouldBeInlined()) { if (!this_value.type()->IsSubtypeOf(method->aggregate_type())) { @@ -2280,9 +2301,10 @@ VisitResult ImplementationVisitor::GenerateCall( size_t j = 0; for (auto t : callable->signature().labels[i].types) { const Type* parameter_type = label->parameter_types[j]; - if (parameter_type != t) { - ReportError("mismatch of label parameters (expected ", *t, " got ", - parameter_type, " for parameter ", i + 1, ")"); + if (!t->IsSubtypeOf(parameter_type)) { + ReportError("mismatch of label parameters (label expects ", + *parameter_type, " but macro produces ", *t, + " for parameter ", i + 1, ")"); } j++; } @@ -2360,6 +2382,7 @@ VisitResult ImplementationVisitor::Visit(CallExpression* expr, if (auto* loc_expr = LocationExpression::DynamicCast(expr->arguments[0])) { LocationReference ref = GetLocationReference(loc_expr); if (ref.IsHeapReference()) return scope.Yield(ref.heap_reference()); + if (ref.IsHeapSlice()) return scope.Yield(ref.heap_slice()); } ReportError("Unable to create a heap reference."); } @@ -2413,7 +2436,7 @@ VisitResult ImplementationVisitor::Visit(CallMethodExpression* expr) { DCHECK_EQ(expr->method->namespace_qualification.size(), 0); QualifiedName qualified_name = QualifiedName(method_name); Callable* callable = nullptr; - callable = LookupMethod(method_name, target, arguments, {}); + callable = LookupMethod(method_name, target_type, arguments, {}); if (GlobalContext::collect_language_server_data()) { LanguageServerData::AddDefinition(expr->method->name->pos, callable->IdentifierPosition()); @@ -2429,7 +2452,7 @@ VisitResult ImplementationVisitor::Visit(IntrinsicCallExpression* expr) { for (Expression* arg : expr->arguments) arguments.parameters.push_back(Visit(arg)); return scope.Yield( - GenerateCall(expr->name, arguments, specialization_types, false)); + GenerateCall(expr->name->value, arguments, specialization_types, false)); } void ImplementationVisitor::GenerateBranch(const VisitResult& condition, @@ -2440,32 +2463,20 @@ void ImplementationVisitor::GenerateBranch(const VisitResult& condition, assembler().Branch(true_block, false_block); } -void ImplementationVisitor::GenerateExpressionBranch( - VisitResultGenerator generator, Block* true_block, Block* false_block) { - // Conditional expressions can either explicitly return a bit - // type, or they can be backed by macros that don't return but - // take a true and false label. By declaring the labels before - // visiting the conditional expression, those label-based - // macro conditionals will be able to find them through normal - // label lookups. - Binding<LocalLabel> true_binding{&LabelBindingsManager::Get(), kTrueLabelName, - LocalLabel{true_block}}; - Binding<LocalLabel> false_binding{&LabelBindingsManager::Get(), - kFalseLabelName, LocalLabel{false_block}}; - StackScope stack_scope(this); - VisitResult expression_result = generator(); - if (!expression_result.type()->IsNever()) { - expression_result = stack_scope.Yield( - GenerateImplicitConvert(TypeOracle::GetBoolType(), expression_result)); - GenerateBranch(expression_result, true_block, false_block); - } +VisitResult ImplementationVisitor::GenerateBoolConstant(bool constant) { + return GenerateImplicitConvert(TypeOracle::GetBoolType(), + VisitResult(TypeOracle::GetConstexprBoolType(), + constant ? "true" : "false")); } void ImplementationVisitor::GenerateExpressionBranch(Expression* expression, Block* true_block, Block* false_block) { - GenerateExpressionBranch([&]() { return this->Visit(expression); }, - true_block, false_block); + StackScope stack_scope(this); + VisitResult expression_result = this->Visit(expression); + expression_result = stack_scope.Yield( + GenerateImplicitConvert(TypeOracle::GetBoolType(), expression_result)); + GenerateBranch(expression_result, true_block, false_block); } VisitResult ImplementationVisitor::GenerateImplicitConvert( @@ -2530,10 +2541,6 @@ StackRange ImplementationVisitor::LowerParameter( range.Extend(parameter_range); } return range; - } else if (type->IsReferenceType()) { - lowered_parameters->Push(parameter_name + ".object"); - lowered_parameters->Push(parameter_name + ".offset"); - return lowered_parameters->TopRange(2); } else { lowered_parameters->Push(parameter_name); return lowered_parameters->TopRange(1); @@ -2663,70 +2670,6 @@ void ImplementationVisitor::Visit(Declarable* declarable) { } } -namespace { -class IfDefScope { - public: - IfDefScope(std::ostream& os, std::string d) : os_(os), d_(std::move(d)) { - os_ << "#ifdef " << d_ << "\n"; - } - ~IfDefScope() { os_ << "#endif // " << d_ << "\n"; } - - private: - std::ostream& os_; - std::string d_; -}; - -class NamespaceScope { - public: - NamespaceScope(std::ostream& os, - std::initializer_list<std::string> namespaces) - : os_(os), d_(std::move(namespaces)) { - for (const std::string& s : d_) { - os_ << "namespace " << s << " {\n"; - } - } - ~NamespaceScope() { - for (auto i = d_.rbegin(); i != d_.rend(); ++i) { - os_ << "} // namespace " << *i << "\n"; - } - } - - private: - std::ostream& os_; - std::vector<std::string> d_; -}; - -class IncludeGuardScope { - public: - IncludeGuardScope(std::ostream& os, std::string file_name) - : os_(os), - d_("V8_GEN_TORQUE_GENERATED_" + CapifyStringWithUnderscores(file_name) + - "_") { - os_ << "#ifndef " << d_ << "\n"; - os_ << "#define " << d_ << "\n\n"; - } - ~IncludeGuardScope() { os_ << "#endif // " << d_ << "\n"; } - - private: - std::ostream& os_; - std::string d_; -}; - -class IncludeObjectMacrosScope { - public: - explicit IncludeObjectMacrosScope(std::ostream& os) : os_(os) { - os_ << "\n// Has to be the last include (doesn't have include guards):\n" - "#include \"src/objects/object-macros.h\"\n"; - } - ~IncludeObjectMacrosScope() { - os_ << "\n#include \"src/objects/object-macros-undef.h\"\n"; - } - - private: - std::ostream& os_; -}; -} // namespace - void ImplementationVisitor::GenerateBuiltinDefinitions( const std::string& output_directory) { std::stringstream new_contents_stream; @@ -2741,7 +2684,7 @@ void ImplementationVisitor::GenerateBuiltinDefinitions( for (auto& declarable : GlobalContext::AllDeclarables()) { Builtin* builtin = Builtin::DynamicCast(declarable.get()); if (!builtin || builtin->IsExternal()) continue; - int firstParameterIndex = 1; + size_t firstParameterIndex = 1; bool declareParameters = true; if (builtin->IsStub()) { new_contents_stream << "TFS(" << builtin->ExternalName(); @@ -2752,24 +2695,22 @@ void ImplementationVisitor::GenerateBuiltinDefinitions( << ", SharedFunctionInfo::kDontAdaptArgumentsSentinel"; declareParameters = false; } else { - assert(builtin->IsFixedArgsJavaScript()); + DCHECK(builtin->IsFixedArgsJavaScript()); // FixedArg javascript builtins need to offer the parameter // count. - int size = static_cast<int>(builtin->parameter_names().size()); - assert(size >= 1); - new_contents_stream << ", " << (std::max(size - 2, 0)); + int parameter_count = + static_cast<int>(builtin->signature().ExplicitCount()); + new_contents_stream << ", " << parameter_count; // And the receiver is explicitly declared. new_contents_stream << ", kReceiver"; - firstParameterIndex = 2; + firstParameterIndex = builtin->signature().implicit_count; } } if (declareParameters) { - int index = 0; - for (const auto& parameter : builtin->parameter_names()) { - if (index >= firstParameterIndex) { - new_contents_stream << ", k" << CamelifyString(parameter->value); - } - index++; + for (size_t i = firstParameterIndex; + i < builtin->parameter_names().size(); ++i) { + Identifier* parameter = builtin->parameter_names()[i]; + new_contents_stream << ", k" << CamelifyString(parameter->value); } } new_contents_stream << ") \\\n"; @@ -2834,15 +2775,31 @@ class FieldOffsetsGenerator { public: explicit FieldOffsetsGenerator(const ClassType* type) : type_(type) {} - virtual void WriteField(const Field& f) = 0; + virtual void WriteField(const Field& f, const std::string& size_string) = 0; virtual void WriteMarker(const std::string& marker) = 0; + virtual void BeginPrivateOffsets() = 0; virtual ~FieldOffsetsGenerator() { CHECK(is_finished_); } void RecordOffsetFor(const Field& f) { CHECK(!is_finished_); UpdateSection(f); - WriteField(f); + // We don't know statically how much space an indexed field takes, so report + // it as zero. + std::string size_string = "0"; + if (!f.index.has_value()) { + size_t field_size; + std::tie(field_size, size_string) = f.GetFieldSizeInformation(); + } + WriteField(f, size_string); + + // Offsets for anything after an indexed field are likely to cause + // confusion, because the indexed field itself takes up a variable amount of + // space. We could not emit them at all, but that might allow an inherited + // kSize to be accessible (and wrong), so we emit them as private. + if (f.index.has_value()) { + BeginPrivateOffsets(); + } } void Finish() { @@ -2923,17 +2880,16 @@ class MacroFieldOffsetsGenerator : public FieldOffsetsGenerator { out_ << "TORQUE_GENERATED_" << CapifyStringWithUnderscores(type_->name()) << "_FIELDS(V) \\\n"; } - virtual void WriteField(const Field& f) { - size_t field_size; - std::string size_string; - std::string machine_type; - std::tie(field_size, size_string) = f.GetFieldSizeInformation(); + void WriteField(const Field& f, const std::string& size_string) override { out_ << "V(k" << CamelifyString(f.name_and_type.name) << "Offset, " << size_string << ") \\\n"; } - virtual void WriteMarker(const std::string& marker) { + void WriteMarker(const std::string& marker) override { out_ << "V(" << marker << ", 0) \\\n"; } + void BeginPrivateOffsets() override { + // Can't do anything meaningful here in the macro generator. + } private: std::ostream& out_; @@ -3025,13 +2981,15 @@ void ImplementationVisitor::GenerateClassFieldOffsets( // TODO(danno): Remove this once all classes use ClassFieldOffsetGenerator // to generate field offsets without the use of macros. - MacroFieldOffsetsGenerator g(header, type); - for (auto f : type->fields()) { - CurrentSourcePosition::Scope scope(f.pos); - g.RecordOffsetFor(f); + if (!type->GenerateCppClassDefinitions()) { + MacroFieldOffsetsGenerator g(header, type); + for (auto f : type->fields()) { + CurrentSourcePosition::Scope scope(f.pos); + g.RecordOffsetFor(f); + } + g.Finish(); + header << "\n"; } - g.Finish(); - header << "\n"; } } const std::string output_header_path = output_directory + "/" + file_name; @@ -3046,11 +3004,7 @@ class ClassFieldOffsetGenerator : public FieldOffsetsGenerator { : FieldOffsetsGenerator(type), hdr_(header), previous_field_end_("P::kHeaderSize") {} - virtual void WriteField(const Field& f) { - size_t field_size; - std::string size_string; - std::string machine_type; - std::tie(field_size, size_string) = f.GetFieldSizeInformation(); + void WriteField(const Field& f, const std::string& size_string) override { std::string field = "k" + CamelifyString(f.name_and_type.name) + "Offset"; std::string field_end = field + "End"; hdr_ << " static constexpr int " << field << " = " << previous_field_end_ @@ -3059,10 +3013,15 @@ class ClassFieldOffsetGenerator : public FieldOffsetsGenerator { << size_string << " - 1;\n"; previous_field_end_ = field_end + " + 1"; } - virtual void WriteMarker(const std::string& marker) { + void WriteMarker(const std::string& marker) override { hdr_ << " static constexpr int " << marker << " = " << previous_field_end_ << ";\n"; } + void BeginPrivateOffsets() override { + // The following section must re-establish public mode (currently done by + // GenerateClassConstructors). + hdr_ << " private:\n"; + } private: std::ostream& hdr_; @@ -3109,8 +3068,6 @@ class CppClassGenerator { }; void CppClassGenerator::GenerateClass() { - hdr_ << "class " << name_ << ";\n\n"; - hdr_ << template_decl() << "\n"; hdr_ << "class " << gen_name_ << " : public P {\n"; hdr_ << " static_assert(std::is_same<" << name_ << ", D>::value,\n" @@ -3118,7 +3075,7 @@ void CppClassGenerator::GenerateClass() { hdr_ << " static_assert(std::is_same<" << super_->name() << ", P>::value,\n" << " \"Pass in " << super_->name() << " as second template parameter for " << gen_name_ << ".\");\n"; - hdr_ << "public: \n"; + hdr_ << " public: \n"; hdr_ << " using Super = P;\n"; for (const Field& f : type_->fields()) { GenerateFieldAccessor(f); @@ -3170,7 +3127,7 @@ void CppClassGenerator::GenerateClassCasts() { } void CppClassGenerator::GenerateClassConstructors() { - hdr_ << "public:\n"; + hdr_ << " public:\n"; hdr_ << " template <class DAlias = D>\n"; hdr_ << " constexpr " << gen_name_ << "() : P() {\n"; hdr_ << " static_assert(std::is_base_of<" << gen_name_ << ", \n"; @@ -3282,9 +3239,9 @@ void CppClassGenerator::GenerateFieldAccessorForObject(const Field& f) { DCHECK(field_type->IsSubtypeOf(TypeOracle::GetObjectType())); const std::string& name = f.name_and_type.name; const std::string offset = "k" + CamelifyString(name) + "Offset"; - const ClassType* class_type = ClassType::DynamicCast(field_type); + base::Optional<const ClassType*> class_type = field_type->ClassSupertype(); - std::string type = class_type ? class_type->name() : "Object"; + std::string type = class_type ? (*class_type)->name() : "Object"; // Generate declarations in header. if (!class_type && field_type != TypeOracle::GetObjectType()) { @@ -3356,20 +3313,42 @@ void ImplementationVisitor::GenerateClassDefinitions( IncludeGuardScope inline_header_guard(inline_header, basename + "-inl.h"); inline_header << "#include \"torque-generated/class-definitions-tq.h\"\n\n"; - inline_header << "#include \"src/objects/objects-inl.h\"\n\n"; + inline_header << "#include \"src/objects/js-promise.h\"\n"; + inline_header << "#include \"src/objects/module.h\"\n"; + inline_header << "#include \"src/objects/objects-inl.h\"\n"; + inline_header << "#include \"src/objects/script.h\"\n\n"; IncludeObjectMacrosScope inline_header_macros(inline_header); NamespaceScope inline_header_namespaces(inline_header, {"v8", "internal"}); implementation << "#include \"torque-generated/class-definitions-tq.h\"\n\n"; implementation << "#include \"torque-generated/class-verifiers-tq.h\"\n\n"; - implementation << "#include \"src/objects/struct-inl.h\"\n\n"; + implementation << "#include \"src/objects/arguments-inl.h\"\n"; + implementation << "#include \"src/objects/js-collection-inl.h\"\n"; + implementation << "#include \"src/objects/embedder-data-array-inl.h\"\n"; + implementation << "#include \"src/objects/js-generator-inl.h\"\n"; + implementation << "#include \"src/objects/js-regexp-inl.h\"\n"; + implementation + << "#include \"src/objects/js-regexp-string-iterator-inl.h\"\n"; + implementation << "#include \"src/objects/literal-objects-inl.h\"\n"; + implementation << "#include \"src/objects/microtask-inl.h\"\n"; + implementation << "#include \"src/objects/module-inl.h\"\n"; + implementation << "#include \"src/objects/promise-inl.h\"\n"; + implementation << "#include \"src/objects/stack-frame-info-inl.h\"\n"; + implementation << "#include \"src/objects/struct-inl.h\"\n"; + implementation << "#include \"src/objects/template-objects-inl.h\"\n\n"; implementation << "#include " "\"torque-generated/internal-class-definitions-tq-inl.h\"\n\n"; NamespaceScope implementation_namespaces(implementation, {"v8", "internal"}); + // Generate forward declarations for every class. + for (const TypeAlias* alias : GlobalContext::GetClasses()) { + const ClassType* type = ClassType::DynamicCast(alias->type()); + header << "class " << type->name() << ";\n"; + } + for (const TypeAlias* alias : GlobalContext::GetClasses()) { const ClassType* type = ClassType::DynamicCast(alias->type()); if (type->GenerateCppClassDefinitions()) { @@ -3724,6 +3703,16 @@ void ReportAllUnusedMacros() { if (macro->IsTorqueMacro() && TorqueMacro::cast(macro)->IsExportedToCSA()) { continue; } + // TODO(gsps): Mark methods of generic structs used if they are used in any + // instantiation + if (Method* method = Method::DynamicCast(macro)) { + if (StructType* struct_type = + StructType::DynamicCast(method->aggregate_type())) { + if (struct_type->GetSpecializedFrom().has_value()) { + continue; + } + } + } std::vector<std::string> ignored_prefixes = {"Convert<", "Cast<", "FromConstexpr<"}; diff --git a/deps/v8/src/torque/implementation-visitor.h b/deps/v8/src/torque/implementation-visitor.h index a572ebb936..eb1a6c4452 100644 --- a/deps/v8/src/torque/implementation-visitor.h +++ b/deps/v8/src/torque/implementation-visitor.h @@ -12,6 +12,7 @@ #include "src/torque/cfg.h" #include "src/torque/declarations.h" #include "src/torque/global-context.h" +#include "src/torque/type-oracle.h" #include "src/torque/types.h" #include "src/torque/utils.h" @@ -52,10 +53,20 @@ class LocationReference { // pointer. static LocationReference HeapReference(VisitResult heap_reference) { LocationReference result; - DCHECK(heap_reference.type()->IsReferenceType()); + DCHECK(StructType::MatchUnaryGeneric(heap_reference.type(), + TypeOracle::GetReferenceGeneric())); result.heap_reference_ = std::move(heap_reference); return result; } + // A reference to an array on the heap. That is, a tagged value, an offset to + // encode an inner pointer, and the number of elements. + static LocationReference HeapSlice(VisitResult heap_slice) { + LocationReference result; + DCHECK(StructType::MatchUnaryGeneric(heap_slice.type(), + TypeOracle::GetSliceGeneric())); + result.heap_slice_ = std::move(heap_slice); + return result; + } static LocationReference ArrayAccess(VisitResult base, VisitResult offset) { LocationReference result; result.eval_function_ = std::string{"[]"}; @@ -69,26 +80,6 @@ class LocationReference { result.eval_function_ = "." + fieldname; result.assign_function_ = "." + fieldname + "="; result.call_arguments_ = {object}; - result.index_field_ = base::nullopt; - return result; - } - static LocationReference IndexedFieldIndexedAccess( - const LocationReference& indexed_field, VisitResult index) { - LocationReference result; - DCHECK(indexed_field.IsIndexedFieldAccess()); - std::string fieldname = *indexed_field.index_field_; - result.eval_function_ = "." + fieldname + "[]"; - result.assign_function_ = "." + fieldname + "[]="; - result.call_arguments_ = indexed_field.call_arguments_; - result.call_arguments_.push_back(index); - result.index_field_ = fieldname; - return result; - } - static LocationReference IndexedFieldAccess(VisitResult object, - std::string fieldname) { - LocationReference result; - result.call_arguments_ = {object}; - result.index_field_ = fieldname; return result; } @@ -109,16 +100,26 @@ class LocationReference { DCHECK(IsHeapReference()); return *heap_reference_; } + bool IsHeapSlice() const { return heap_slice_.has_value(); } + const VisitResult& heap_slice() const { + DCHECK(IsHeapSlice()); + return *heap_slice_; + } const Type* ReferencedType() const { if (IsHeapReference()) { - return ReferenceType::cast(heap_reference().type())->referenced_type(); + return *StructType::MatchUnaryGeneric(heap_reference().type(), + TypeOracle::GetReferenceGeneric()); + } else if (IsHeapSlice()) { + return *StructType::MatchUnaryGeneric(heap_slice().type(), + TypeOracle::GetSliceGeneric()); } return GetVisitResult().type(); } const VisitResult& GetVisitResult() const { if (IsVariableAccess()) return variable(); + if (IsHeapSlice()) return heap_slice(); DCHECK(IsTemporary()); return temporary(); } @@ -129,13 +130,6 @@ class LocationReference { return *temporary_description_; } - bool IsArrayField() const { return index_field_.has_value(); } - bool IsIndexedFieldAccess() const { - return IsArrayField() && !IsCallAccess(); - } - bool IsIndexedFieldIndexedAccess() const { - return IsArrayField() && IsCallAccess(); - } bool IsCallAccess() const { bool is_call_access = eval_function_.has_value(); DCHECK_EQ(is_call_access, assign_function_.has_value()); @@ -163,10 +157,10 @@ class LocationReference { base::Optional<VisitResult> temporary_; base::Optional<std::string> temporary_description_; base::Optional<VisitResult> heap_reference_; + base::Optional<VisitResult> heap_slice_; base::Optional<std::string> eval_function_; base::Optional<std::string> assign_function_; VisitResultVector call_arguments_; - base::Optional<std::string> index_field_; base::Optional<Binding<LocalValue>*> binding_; LocationReference() = default; @@ -354,6 +348,7 @@ class ImplementationVisitor { void GenerateClassDefinitions(const std::string& output_directory); void GenerateInstanceTypes(const std::string& output_directory); void GenerateClassVerifiers(const std::string& output_directory); + void GenerateClassDebugReaders(const std::string& output_directory); void GenerateExportedMacrosAssembler(const std::string& output_directory); void GenerateCSATypes(const std::string& output_directory); void GenerateCppForInternalClasses(const std::string& output_directory); @@ -361,27 +356,26 @@ class ImplementationVisitor { VisitResult Visit(Expression* expr); const Type* Visit(Statement* stmt); + void CheckInitializersWellformed( + const std::string& aggregate_name, + const std::vector<Field>& aggregate_fields, + const std::vector<NameAndExpression>& initializers, + bool ignore_first_field = false); + InitializerResults VisitInitializerResults( - const AggregateType* aggregate, + const ClassType* class_type, const std::vector<NameAndExpression>& expressions); void InitializeFieldFromSpread(VisitResult object, const Field& field, const InitializerResults& initializer_results); - size_t InitializeAggregateHelper( - const AggregateType* aggregate_type, VisitResult allocate_result, - const InitializerResults& initializer_results); - VisitResult AddVariableObjectSize( VisitResult object_size, const ClassType* current_class, const InitializerResults& initializer_results); - void InitializeAggregate(const AggregateType* aggregate_type, - VisitResult allocate_result, - const InitializerResults& initializer_results); + void InitializeClass(const ClassType* class_type, VisitResult allocate_result, + const InitializerResults& initializer_results); - VisitResult TemporaryUninitializedStruct(const StructType* struct_type, - const std::string& reason); VisitResult Visit(StructExpression* decl); LocationReference GetLocationReference(Expression* location); @@ -570,7 +564,8 @@ class ImplementationVisitor { const Arguments& arguments, const TypeVector& specialization_types); - Method* LookupMethod(const std::string& name, LocationReference target, + Method* LookupMethod(const std::string& name, + const AggregateType* receiver_type, const Arguments& arguments, const TypeVector& specialization_types); @@ -608,9 +603,8 @@ class ImplementationVisitor { void GenerateBranch(const VisitResult& condition, Block* true_block, Block* false_block); - using VisitResultGenerator = std::function<VisitResult()>; - void GenerateExpressionBranch(VisitResultGenerator, Block* true_block, - Block* false_block); + VisitResult GenerateBoolConstant(bool constant); + void GenerateExpressionBranch(Expression* expression, Block* true_block, Block* false_block); diff --git a/deps/v8/src/torque/instructions.cc b/deps/v8/src/torque/instructions.cc index 36a22ee8fa..5bc2149f41 100644 --- a/deps/v8/src/torque/instructions.cc +++ b/deps/v8/src/torque/instructions.cc @@ -133,7 +133,7 @@ void CallCsaMacroInstruction::TypeInstruction(Stack<const Type*>* stack, if (catch_block) { Stack<const Type*> catch_stack = *stack; - catch_stack.Push(TypeOracle::GetObjectType()); + catch_stack.Push(TypeOracle::GetJSAnyType()); (*catch_block)->SetInputTypes(catch_stack); } @@ -170,7 +170,7 @@ void CallCsaMacroAndBranchInstruction::TypeInstruction( if (catch_block) { Stack<const Type*> catch_stack = *stack; - catch_stack.Push(TypeOracle::GetObjectType()); + catch_stack.Push(TypeOracle::GetJSAnyType()); (*catch_block)->SetInputTypes(catch_stack); } @@ -201,7 +201,7 @@ void CallBuiltinInstruction::TypeInstruction(Stack<const Type*>* stack, if (catch_block) { Stack<const Type*> catch_stack = *stack; - catch_stack.Push(TypeOracle::GetObjectType()); + catch_stack.Push(TypeOracle::GetJSAnyType()); (*catch_block)->SetInputTypes(catch_stack); } @@ -236,7 +236,7 @@ void CallRuntimeInstruction::TypeInstruction(Stack<const Type*>* stack, if (catch_block) { Stack<const Type*> catch_stack = *stack; - catch_stack.Push(TypeOracle::GetObjectType()); + catch_stack.Push(TypeOracle::GetJSAnyType()); (*catch_block)->SetInputTypes(catch_stack); } @@ -292,15 +292,14 @@ void UnsafeCastInstruction::TypeInstruction(Stack<const Type*>* stack, void CreateFieldReferenceInstruction::TypeInstruction( Stack<const Type*>* stack, ControlFlowGraph* cfg) const { - ExpectSubtype(stack->Pop(), class_type); - stack->Push(TypeOracle::GetHeapObjectType()); + ExpectSubtype(stack->Top(), type); stack->Push(TypeOracle::GetIntPtrType()); } void LoadReferenceInstruction::TypeInstruction(Stack<const Type*>* stack, ControlFlowGraph* cfg) const { ExpectType(TypeOracle::GetIntPtrType(), stack->Pop()); - ExpectType(TypeOracle::GetHeapObjectType(), stack->Pop()); + ExpectSubtype(stack->Pop(), TypeOracle::GetHeapObjectType()); DCHECK_EQ(std::vector<const Type*>{type}, LowerType(type)); stack->Push(type); } @@ -309,7 +308,7 @@ void StoreReferenceInstruction::TypeInstruction(Stack<const Type*>* stack, ControlFlowGraph* cfg) const { ExpectSubtype(stack->Pop(), type); ExpectType(TypeOracle::GetIntPtrType(), stack->Pop()); - ExpectType(TypeOracle::GetHeapObjectType(), stack->Pop()); + ExpectSubtype(stack->Pop(), TypeOracle::GetHeapObjectType()); } bool CallRuntimeInstruction::IsBlockTerminator() const { diff --git a/deps/v8/src/torque/instructions.h b/deps/v8/src/torque/instructions.h index 3136b58321..fe3b26b86f 100644 --- a/deps/v8/src/torque/instructions.h +++ b/deps/v8/src/torque/instructions.h @@ -206,10 +206,9 @@ struct NamespaceConstantInstruction : InstructionBase { struct CreateFieldReferenceInstruction : InstructionBase { TORQUE_INSTRUCTION_BOILERPLATE() - CreateFieldReferenceInstruction(const ClassType* class_type, - std::string field_name) - : class_type(class_type), field_name(std::move(field_name)) {} - const ClassType* class_type; + CreateFieldReferenceInstruction(const Type* type, std::string field_name) + : type(type), field_name(std::move(field_name)) {} + const Type* type; std::string field_name; }; diff --git a/deps/v8/src/torque/torque-compiler.cc b/deps/v8/src/torque/torque-compiler.cc index a3da95c747..3968b001fb 100644 --- a/deps/v8/src/torque/torque-compiler.cc +++ b/deps/v8/src/torque/torque-compiler.cc @@ -53,6 +53,7 @@ void CompileCurrentAst(TorqueCompilerOptions options) { if (options.force_assert_statements) { GlobalContext::SetForceAssertStatements(); } + TargetArchitecture::Scope target_architecture(options.force_32bit_output); TypeOracle::Scope type_oracle; // Two-step process of predeclaration + resolution allows to resolve type @@ -83,6 +84,7 @@ void CompileCurrentAst(TorqueCompilerOptions options) { implementation_visitor.GeneratePrintDefinitions(output_directory); implementation_visitor.GenerateClassDefinitions(output_directory); implementation_visitor.GenerateClassVerifiers(output_directory); + implementation_visitor.GenerateClassDebugReaders(output_directory); implementation_visitor.GenerateExportedMacrosAssembler(output_directory); implementation_visitor.GenerateCSATypes(output_directory); implementation_visitor.GenerateInstanceTypes(output_directory); diff --git a/deps/v8/src/torque/torque-compiler.h b/deps/v8/src/torque/torque-compiler.h index 32680986fd..df81d60d3e 100644 --- a/deps/v8/src/torque/torque-compiler.h +++ b/deps/v8/src/torque/torque-compiler.h @@ -24,6 +24,12 @@ struct TorqueCompilerOptions { // language server support for statements inside asserts, this flag // can force generate them. bool force_assert_statements = false; + + // Forge (Google3) can only run 64-bit executables. As Torque runs as part + // of the build process, we need a "cross-compile" mode when we target 32-bit + // architectures. Note that this does not needed in Chromium/V8 land, since we + // always build with the same bit width as the target architecture. + bool force_32bit_output = false; }; struct TorqueCompilerResult { diff --git a/deps/v8/src/torque/torque-parser.cc b/deps/v8/src/torque/torque-parser.cc index 0a371b79f9..d9973dde3c 100644 --- a/deps/v8/src/torque/torque-parser.cc +++ b/deps/v8/src/torque/torque-parser.cc @@ -108,13 +108,12 @@ V8_EXPORT_PRIVATE const ParseResultTypeId ParseResultHolder<NameAndExpression>::id = ParseResultTypeId::kNameAndExpression; template <> -V8_EXPORT_PRIVATE const ParseResultTypeId - ParseResultHolder<ConditionalAnnotation>::id = - ParseResultTypeId::kConditionalAnnotation; +V8_EXPORT_PRIVATE const ParseResultTypeId ParseResultHolder<Annotation>::id = + ParseResultTypeId::kAnnotation; template <> V8_EXPORT_PRIVATE const ParseResultTypeId - ParseResultHolder<base::Optional<ConditionalAnnotation>>::id = - ParseResultTypeId::kOptionalConditionalAnnotation; + ParseResultHolder<std::vector<Annotation>>::id = + ParseResultTypeId::kVectorOfAnnotation; template <> V8_EXPORT_PRIVATE const ParseResultTypeId ParseResultHolder<ClassFieldExpression>::id = @@ -360,7 +359,7 @@ base::Optional<ParseResult> MakeBinaryOperator( base::Optional<ParseResult> MakeIntrinsicCallExpression( ParseResultIterator* child_results) { - auto callee = child_results->NextAs<std::string>(); + auto callee = child_results->NextAs<Identifier*>(); auto generic_arguments = child_results->NextAs<std::vector<TypeExpression*>>(); auto args = child_results->NextAs<std::vector<Expression*>>(); @@ -472,29 +471,27 @@ base::Optional<ParseResult> MakeExternalMacro( auto operator_name = child_results->NextAs<base::Optional<std::string>>(); auto external_assembler_name = child_results->NextAs<base::Optional<std::string>>(); - auto name = child_results->NextAs<std::string>(); + auto name = child_results->NextAs<Identifier*>(); auto generic_parameters = child_results->NextAs<GenericParameters>(); LintGenericParameters(generic_parameters); auto args = child_results->NextAs<ParameterList>(); auto return_type = child_results->NextAs<TypeExpression*>(); auto labels = child_results->NextAs<LabelAndTypesVector>(); - MacroDeclaration* macro = MakeNode<ExternalMacroDeclaration>( + + Declaration* result = MakeNode<ExternalMacroDeclaration>( transitioning, external_assembler_name ? *external_assembler_name : "CodeStubAssembler", name, operator_name, args, return_type, labels); - Declaration* result; - if (generic_parameters.empty()) { - result = MakeNode<StandardDeclaration>(macro, base::nullopt); - } else { - result = MakeNode<GenericDeclaration>(macro, generic_parameters); + if (!generic_parameters.empty()) { + Error("External builtins cannot be generic."); } return ParseResult{result}; } base::Optional<ParseResult> MakeIntrinsicDeclaration( ParseResultIterator* child_results) { - auto name = child_results->NextAs<std::string>(); + auto name = child_results->NextAs<Identifier*>(); auto generic_parameters = child_results->NextAs<GenericParameters>(); LintGenericParameters(generic_parameters); @@ -502,19 +499,17 @@ base::Optional<ParseResult> MakeIntrinsicDeclaration( auto return_type = child_results->NextAs<TypeExpression*>(); auto body = child_results->NextAs<base::Optional<Statement*>>(); LabelAndTypesVector labels; - CallableNode* callable = nullptr; + CallableDeclaration* declaration; if (body) { - callable = MakeNode<TorqueMacroDeclaration>( + declaration = MakeNode<TorqueMacroDeclaration>( false, name, base::Optional<std::string>{}, args, return_type, labels, - false); + false, body); } else { - callable = MakeNode<IntrinsicDeclaration>(name, args, return_type); + declaration = MakeNode<IntrinsicDeclaration>(name, args, return_type); } - Declaration* result; - if (generic_parameters.empty()) { - result = MakeNode<StandardDeclaration>(callable, body); - } else { - result = MakeNode<GenericDeclaration>(callable, generic_parameters, body); + Declaration* result = declaration; + if (!generic_parameters.empty()) { + result = MakeNode<GenericDeclaration>(generic_parameters, declaration); } return ParseResult{result}; } @@ -524,8 +519,8 @@ base::Optional<ParseResult> MakeTorqueMacroDeclaration( auto export_to_csa = child_results->NextAs<bool>(); auto transitioning = child_results->NextAs<bool>(); auto operator_name = child_results->NextAs<base::Optional<std::string>>(); - auto name = child_results->NextAs<std::string>(); - if (!IsUpperCamelCase(name)) { + auto name = child_results->NextAs<Identifier*>(); + if (!IsUpperCamelCase(name->value)) { NamingConventionError("Macro", name, "UpperCamelCase"); } @@ -536,16 +531,15 @@ base::Optional<ParseResult> MakeTorqueMacroDeclaration( auto return_type = child_results->NextAs<TypeExpression*>(); auto labels = child_results->NextAs<LabelAndTypesVector>(); auto body = child_results->NextAs<base::Optional<Statement*>>(); - MacroDeclaration* macro = - MakeNode<TorqueMacroDeclaration>(transitioning, name, operator_name, args, - return_type, labels, export_to_csa); - Declaration* result; + CallableDeclaration* declaration = MakeNode<TorqueMacroDeclaration>( + transitioning, name, operator_name, args, return_type, labels, + export_to_csa, body); + Declaration* result = declaration; if (generic_parameters.empty()) { if (!body) ReportError("A non-generic declaration needs a body."); - result = MakeNode<StandardDeclaration>(macro, *body); } else { if (export_to_csa) ReportError("Cannot export generics to CSA."); - result = MakeNode<GenericDeclaration>(macro, generic_parameters, body); + result = MakeNode<GenericDeclaration>(generic_parameters, declaration); } return ParseResult{result}; } @@ -554,8 +548,8 @@ base::Optional<ParseResult> MakeTorqueBuiltinDeclaration( ParseResultIterator* child_results) { auto transitioning = child_results->NextAs<bool>(); auto javascript_linkage = child_results->NextAs<bool>(); - auto name = child_results->NextAs<std::string>(); - if (!IsUpperCamelCase(name)) { + auto name = child_results->NextAs<Identifier*>(); + if (!IsUpperCamelCase(name->value)) { NamingConventionError("Builtin", name, "UpperCamelCase"); } @@ -565,14 +559,13 @@ base::Optional<ParseResult> MakeTorqueBuiltinDeclaration( auto args = child_results->NextAs<ParameterList>(); auto return_type = child_results->NextAs<TypeExpression*>(); auto body = child_results->NextAs<base::Optional<Statement*>>(); - BuiltinDeclaration* builtin = MakeNode<TorqueBuiltinDeclaration>( - transitioning, javascript_linkage, name, args, return_type); - Declaration* result; + CallableDeclaration* declaration = MakeNode<TorqueBuiltinDeclaration>( + transitioning, javascript_linkage, name, args, return_type, body); + Declaration* result = declaration; if (generic_parameters.empty()) { if (!body) ReportError("A non-generic declaration needs a body."); - result = MakeNode<StandardDeclaration>(builtin, *body); } else { - result = MakeNode<GenericDeclaration>(builtin, generic_parameters, body); + result = MakeNode<GenericDeclaration>(generic_parameters, declaration); } return ParseResult{result}; } @@ -649,8 +642,8 @@ base::Optional<ParseResult> MakeMethodDeclaration( ParseResultIterator* child_results) { auto transitioning = child_results->NextAs<bool>(); auto operator_name = child_results->NextAs<base::Optional<std::string>>(); - auto name = child_results->NextAs<std::string>(); - if (!IsUpperCamelCase(name)) { + auto name = child_results->NextAs<Identifier*>(); + if (!IsUpperCamelCase(name->value)) { NamingConventionError("Method", name, "UpperCamelCase"); } @@ -658,39 +651,66 @@ base::Optional<ParseResult> MakeMethodDeclaration( auto return_type = child_results->NextAs<TypeExpression*>(); auto labels = child_results->NextAs<LabelAndTypesVector>(); auto body = child_results->NextAs<Statement*>(); - MacroDeclaration* macro = MakeNode<TorqueMacroDeclaration>( - transitioning, name, operator_name, args, return_type, labels, false); - Declaration* result = MakeNode<StandardDeclaration>(macro, body); + Declaration* result = + MakeNode<TorqueMacroDeclaration>(transitioning, name, operator_name, args, + return_type, labels, false, body); return ParseResult{result}; } class AnnotationSet { public: AnnotationSet(ParseResultIterator* iter, - const std::set<std::string>& allowed) { - auto list = iter->NextAs<std::vector<Identifier*>>(); - for (const Identifier* i : list) { - if (allowed.find(i->value) == allowed.end()) { - Lint("Annotation ", i->value, " is not allowed here").Position(i->pos); - } - if (!set_.insert(i->value).second) { - Lint("Duplicate annotation ", i->value).Position(i->pos); + const std::set<std::string>& allowed_without_param, + const std::set<std::string>& allowed_with_param) { + auto list = iter->NextAs<std::vector<Annotation>>(); + for (const Annotation& a : list) { + if (a.param.has_value()) { + if (allowed_with_param.find(a.name->value) == + allowed_with_param.end()) { + const char* error_message = + allowed_without_param.find(a.name->value) == + allowed_without_param.end() + ? " is not allowed here" + : " cannot have parameter here"; + Lint("Annotation ", a.name->value, error_message) + .Position(a.name->pos); + } + map_[a.name->value].push_back(*a.param); + } else { + if (allowed_without_param.find(a.name->value) == + allowed_without_param.end()) { + const char* error_message = + allowed_with_param.find(a.name->value) == allowed_with_param.end() + ? " is not allowed here" + : " requires a parameter here"; + Lint("Annotation ", a.name->value, error_message) + .Position(a.name->pos); + } + if (!set_.insert(a.name->value).second) { + Lint("Duplicate annotation ", a.name->value).Position(a.name->pos); + } } } } bool Contains(const std::string& s) { return set_.find(s) != set_.end(); } + const std::vector<std::string>& GetParams(const std::string& s) { + return map_[s]; + } private: std::set<std::string> set_; + std::map<std::string, std::vector<std::string>> map_; }; base::Optional<ParseResult> MakeClassDeclaration( ParseResultIterator* child_results) { AnnotationSet annotations( - child_results, {"@generatePrint", "@noVerifier", "@abstract", - "@dirtyInstantiatedAbstractClass", - "@hasSameInstanceTypeAsParent", "@generateCppClass"}); + child_results, + {"@generatePrint", "@noVerifier", "@abstract", + "@dirtyInstantiatedAbstractClass", "@hasSameInstanceTypeAsParent", + "@generateCppClass"}, + {}); ClassFlags flags = ClassFlag::kNone; bool generate_print = annotations.Contains("@generatePrint"); if (generate_print) flags |= ClassFlag::kGeneratePrint; @@ -726,15 +746,18 @@ base::Optional<ParseResult> MakeClassDeclaration( // Filter to only include fields that should be present based on decoration. std::vector<ClassFieldExpression> fields; - std::copy_if(fields_raw.begin(), fields_raw.end(), std::back_inserter(fields), - [](const ClassFieldExpression& exp) { - if (!exp.conditional.has_value()) return true; - const ConditionalAnnotation& conditional = *exp.conditional; - return conditional.type == ConditionalAnnotationType::kPositive - ? BuildFlags::GetFlag(conditional.condition, "@if") - : !BuildFlags::GetFlag(conditional.condition, - "@ifnot"); - }); + std::copy_if( + fields_raw.begin(), fields_raw.end(), std::back_inserter(fields), + [](const ClassFieldExpression& exp) { + for (const ConditionalAnnotation& condition : exp.conditions) { + if (condition.type == ConditionalAnnotationType::kPositive + ? !BuildFlags::GetFlag(condition.condition, "@if") + : BuildFlags::GetFlag(condition.condition, "@ifnot")) { + return false; + } + } + return true; + }); Declaration* result = MakeNode<ClassDeclaration>( name, flags, std::move(extends), std::move(generates), std::move(methods), @@ -756,6 +779,7 @@ base::Optional<ParseResult> MakeNamespaceDeclaration( base::Optional<ParseResult> MakeSpecializationDeclaration( ParseResultIterator* child_results) { + auto transitioning = child_results->NextAs<bool>(); auto name = child_results->NextAs<Identifier*>(); auto generic_parameters = child_results->NextAs<std::vector<TypeExpression*>>(); @@ -765,8 +789,8 @@ base::Optional<ParseResult> MakeSpecializationDeclaration( auto body = child_results->NextAs<Statement*>(); CheckNotDeferredStatement(body); Declaration* result = MakeNode<SpecializationDeclaration>( - std::move(name), std::move(generic_parameters), std::move(parameters), - return_type, std::move(labels), body); + transitioning, std::move(name), std::move(generic_parameters), + std::move(parameters), return_type, std::move(labels), body); return ParseResult{result}; } @@ -817,19 +841,16 @@ base::Optional<ParseResult> MakeExternalBuiltin( ParseResultIterator* child_results) { auto transitioning = child_results->NextAs<bool>(); auto js_linkage = child_results->NextAs<bool>(); - auto name = child_results->NextAs<std::string>(); + auto name = child_results->NextAs<Identifier*>(); auto generic_parameters = child_results->NextAs<GenericParameters>(); LintGenericParameters(generic_parameters); auto args = child_results->NextAs<ParameterList>(); auto return_type = child_results->NextAs<TypeExpression*>(); - BuiltinDeclaration* builtin = MakeNode<ExternalBuiltinDeclaration>( + Declaration* result = MakeNode<ExternalBuiltinDeclaration>( transitioning, js_linkage, name, args, return_type); - Declaration* result; - if (generic_parameters.empty()) { - result = MakeNode<StandardDeclaration>(builtin, base::nullopt); - } else { - result = MakeNode<GenericDeclaration>(builtin, generic_parameters); + if (!generic_parameters.empty()) { + Error("External builtins cannot be generic."); } return ParseResult{result}; } @@ -837,12 +858,11 @@ base::Optional<ParseResult> MakeExternalBuiltin( base::Optional<ParseResult> MakeExternalRuntime( ParseResultIterator* child_results) { auto transitioning = child_results->NextAs<bool>(); - auto name = child_results->NextAs<std::string>(); + auto name = child_results->NextAs<Identifier*>(); auto args = child_results->NextAs<ParameterList>(); auto return_type = child_results->NextAs<TypeExpression*>(); - ExternalRuntimeDeclaration* runtime = MakeNode<ExternalRuntimeDeclaration>( + Declaration* result = MakeNode<ExternalRuntimeDeclaration>( transitioning, name, args, return_type); - Declaration* result = MakeNode<StandardDeclaration>(runtime, base::nullopt); return ParseResult{result}; } @@ -879,7 +899,11 @@ base::Optional<ParseResult> MakeFunctionTypeExpression( base::Optional<ParseResult> MakeReferenceTypeExpression( ParseResultIterator* child_results) { auto referenced_type = child_results->NextAs<TypeExpression*>(); - TypeExpression* result = MakeNode<ReferenceTypeExpression>(referenced_type); + std::vector<std::string> namespace_qualification{ + TORQUE_INTERNAL_NAMESPACE_STRING}; + std::vector<TypeExpression*> generic_arguments{referenced_type}; + TypeExpression* result = MakeNode<BasicTypeExpression>( + namespace_qualification, REFERENCE_TYPE_STRING, generic_arguments); return ParseResult{result}; } @@ -1141,7 +1165,7 @@ 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>{}, "Object", std::vector<TypeExpression*>{})); + std::vector<std::string>{}, "JSAny", std::vector<TypeExpression*>{})); parameters.has_varargs = false; LabelBlock* result = MakeNode<LabelBlock>( MakeNode<Identifier>(kCatchLabelName), std::move(parameters), body); @@ -1327,22 +1351,22 @@ base::Optional<ParseResult> MakeNameAndExpressionFromExpression( ReportError("Constructor parameters need to be named."); } -base::Optional<ParseResult> MakeConditionalAnnotation( - ParseResultIterator* child_results) { - auto type_str = child_results->NextAs<Identifier*>()->value; - DCHECK(type_str == "@if" || type_str == "@ifnot"); - ConditionalAnnotationType type = type_str == "@if" - ? ConditionalAnnotationType::kPositive - : ConditionalAnnotationType::kNegative; - auto condition = child_results->NextAs<std::string>(); - return ParseResult{ConditionalAnnotation{condition, type}}; +base::Optional<ParseResult> MakeAnnotation(ParseResultIterator* child_results) { + return ParseResult{ + Annotation{child_results->NextAs<Identifier*>(), + child_results->NextAs<base::Optional<std::string>>()}}; } base::Optional<ParseResult> MakeClassField(ParseResultIterator* child_results) { - auto conditional = - child_results->NextAs<base::Optional<ConditionalAnnotation>>(); - AnnotationSet annotations(child_results, {"@noVerifier"}); + AnnotationSet annotations(child_results, {"@noVerifier"}, {"@if", "@ifnot"}); bool generate_verify = !annotations.Contains("@noVerifier"); + std::vector<ConditionalAnnotation> conditions; + for (const std::string& condition : annotations.GetParams("@if")) { + conditions.push_back({condition, ConditionalAnnotationType::kPositive}); + } + for (const std::string& condition : annotations.GetParams("@ifnot")) { + conditions.push_back({condition, ConditionalAnnotationType::kNegative}); + } auto weak = child_results->NextAs<bool>(); auto const_qualified = child_results->NextAs<bool>(); auto name = child_results->NextAs<Identifier*>(); @@ -1350,7 +1374,7 @@ base::Optional<ParseResult> MakeClassField(ParseResultIterator* child_results) { auto type = child_results->NextAs<TypeExpression*>(); return ParseResult{ClassFieldExpression{{name, type}, index, - conditional, + std::move(conditions), weak, const_qualified, generate_verify}}; @@ -1479,15 +1503,12 @@ struct TorqueGrammar : Grammar { Symbol name = {Rule({&identifier}, MakeIdentifier)}; // Result: Identifier* - Symbol annotation = { + Symbol annotationName = { Rule({Pattern(MatchAnnotation)}, MakeIdentifierFromMatchedInput)}; - // Result: std::vector<Identifier*> - Symbol* annotations = List<Identifier*>(&annotation); - // Result: std::string Symbol intrinsicName = { - Rule({Pattern(MatchIntrinsicName)}, YieldMatchedInput)}; + Rule({Pattern(MatchIntrinsicName)}, MakeIdentifierFromMatchedInput)}; // Result: std::string Symbol stringLiteral = { @@ -1501,6 +1522,22 @@ struct TorqueGrammar : Grammar { Rule({Pattern(MatchDecimalLiteral)}, YieldMatchedInput), Rule({Pattern(MatchHexLiteral)}, YieldMatchedInput)}; + // Result: std::string + Symbol annotationParameter = {Rule({&identifier}), Rule({&decimalLiteral}), + Rule({&externalString})}; + + // Result: std::string + Symbol annotationParameters = { + Rule({Token("("), &annotationParameter, Token(")")})}; + + // Result: Annotation + Symbol annotation = { + Rule({&annotationName, Optional<std::string>(&annotationParameters)}, + MakeAnnotation)}; + + // Result: std::vector<Annotation> + Symbol* annotations = List<Annotation>(&annotation); + // Result: TypeList Symbol* typeList = List<TypeExpression*>(&type, Token(",")); @@ -1578,14 +1615,8 @@ struct TorqueGrammar : Grammar { Symbol* optionalArraySpecifier = Optional<std::string>(Sequence({Token("["), &identifier, Token("]")})); - // Result: ConditionalAnnotation - Symbol conditionalAnnotation = { - Rule({OneOf({"@if", "@ifnot"}), Token("("), &identifier, Token(")")}, - MakeConditionalAnnotation)}; - Symbol classField = { - Rule({Optional<ConditionalAnnotation>(&conditionalAnnotation), - annotations, CheckIf(Token("weak")), CheckIf(Token("const")), &name, + Rule({annotations, CheckIf(Token("weak")), CheckIf(Token("const")), &name, optionalArraySpecifier, Token(":"), &type, Token(";")}, MakeClassField)}; @@ -1857,8 +1888,8 @@ struct TorqueGrammar : Grammar { Symbol method = {Rule( {CheckIf(Token("transitioning")), Optional<std::string>(Sequence({Token("operator"), &externalString})), - &identifier, ¶meterListNoVararg, &optionalReturnType, - optionalLabelList, &block}, + &name, ¶meterListNoVararg, &optionalReturnType, optionalLabelList, + &block}, MakeMethodDeclaration)}; // Result: std::vector<Declaration*> @@ -1900,34 +1931,34 @@ struct TorqueGrammar : Grammar { Optional<std::string>( Sequence({Token("operator"), &externalString})), Token("macro"), - Optional<std::string>(Sequence({&identifier, Token("::")})), - &identifier, TryOrDefault<GenericParameters>(&genericParameters), + Optional<std::string>(Sequence({&identifier, Token("::")})), &name, + TryOrDefault<GenericParameters>(&genericParameters), &typeListMaybeVarArgs, &optionalReturnType, optionalLabelList, Token(";")}, AsSingletonVector<Declaration*, MakeExternalMacro>()), Rule({Token("extern"), CheckIf(Token("transitioning")), - CheckIf(Token("javascript")), Token("builtin"), &identifier, + CheckIf(Token("javascript")), Token("builtin"), &name, TryOrDefault<GenericParameters>(&genericParameters), &typeListMaybeVarArgs, &optionalReturnType, Token(";")}, AsSingletonVector<Declaration*, MakeExternalBuiltin>()), - Rule( - {Token("extern"), CheckIf(Token("transitioning")), Token("runtime"), - &identifier, &typeListMaybeVarArgs, &optionalReturnType, Token(";")}, - AsSingletonVector<Declaration*, MakeExternalRuntime>()), + Rule({Token("extern"), CheckIf(Token("transitioning")), Token("runtime"), + &name, &typeListMaybeVarArgs, &optionalReturnType, Token(";")}, + AsSingletonVector<Declaration*, MakeExternalRuntime>()), Rule({CheckIf(Token("@export")), CheckIf(Token("transitioning")), Optional<std::string>( Sequence({Token("operator"), &externalString})), - Token("macro"), &identifier, + Token("macro"), &name, TryOrDefault<GenericParameters>(&genericParameters), ¶meterListNoVararg, &optionalReturnType, optionalLabelList, &optionalBody}, AsSingletonVector<Declaration*, MakeTorqueMacroDeclaration>()), Rule({CheckIf(Token("transitioning")), CheckIf(Token("javascript")), - Token("builtin"), &identifier, + Token("builtin"), &name, TryOrDefault<GenericParameters>(&genericParameters), ¶meterListAllowVararg, &optionalReturnType, &optionalBody}, AsSingletonVector<Declaration*, MakeTorqueBuiltinDeclaration>()), - Rule({&name, &genericSpecializationTypeList, ¶meterListAllowVararg, + Rule({CheckIf(Token("transitioning")), &name, + &genericSpecializationTypeList, ¶meterListAllowVararg, &optionalReturnType, optionalLabelList, &block}, AsSingletonVector<Declaration*, MakeSpecializationDeclaration>()), Rule({Token("#include"), &externalString}, diff --git a/deps/v8/src/torque/torque.cc b/deps/v8/src/torque/torque.cc index e759ce613c..ad7551f8aa 100644 --- a/deps/v8/src/torque/torque.cc +++ b/deps/v8/src/torque/torque.cc @@ -19,19 +19,24 @@ std::string ErrorPrefixFor(TorqueMessage::Kind kind) { } int WrappedMain(int argc, const char** argv) { - std::string output_directory; - std::string v8_root; + TorqueCompilerOptions options; + options.collect_language_server_data = false; + options.force_assert_statements = false; + std::vector<std::string> files; for (int i = 1; i < argc; ++i) { // Check for options - if (std::string(argv[i]) == "-o") { - output_directory = argv[++i]; - } else if (std::string(argv[i]) == "-v8-root") { - v8_root = std::string(argv[++i]); + const std::string argument(argv[i]); + if (argument == "-o") { + options.output_directory = argv[++i]; + } else if (argument == "-v8-root") { + options.v8_root = std::string(argv[++i]); + } else if (argument == "-m32") { + options.force_32bit_output = true; } else { // Otherwise it's a .tq file. Remember it for compilation. - files.emplace_back(argv[i]); + files.emplace_back(std::move(argument)); if (!StringEndsWith(files.back(), ".tq")) { std::cerr << "Unexpected command-line argument \"" << files.back() << "\", expected a .tq file.\n"; @@ -40,12 +45,6 @@ int WrappedMain(int argc, const char** argv) { } } - TorqueCompilerOptions options; - options.output_directory = std::move(output_directory); - options.v8_root = std::move(v8_root); - options.collect_language_server_data = false; - options.force_assert_statements = false; - TorqueCompilerResult result = CompileTorque(files, options); // PositionAsString requires the SourceFileMap to be set to diff --git a/deps/v8/src/torque/type-inference.cc b/deps/v8/src/torque/type-inference.cc new file mode 100644 index 0000000000..abd875f4f6 --- /dev/null +++ b/deps/v8/src/torque/type-inference.cc @@ -0,0 +1,121 @@ +// 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. + +#include "src/torque/type-inference.h" + +namespace v8 { +namespace internal { +namespace torque { + +TypeArgumentInference::TypeArgumentInference( + const NameVector& type_parameters, + const TypeVector& explicit_type_arguments, + const std::vector<TypeExpression*>& term_parameters, + const TypeVector& term_argument_types) + : num_explicit_(explicit_type_arguments.size()), + type_parameter_from_name_(type_parameters.size()), + inferred_(type_parameters.size()) { + if (num_explicit_ > type_parameters.size()) { + Fail("more explicit type arguments than expected"); + return; + } + if (term_parameters.size() != term_argument_types.size()) { + Fail("number of term parameters does not match number of term arguments!"); + return; + } + + for (size_t i = 0; i < type_parameters.size(); i++) { + type_parameter_from_name_[type_parameters[i]->value] = i; + } + for (size_t i = 0; i < num_explicit_; i++) { + inferred_[i] = {explicit_type_arguments[i]}; + } + + for (size_t i = 0; i < term_parameters.size(); i++) { + Match(term_parameters[i], term_argument_types[i]); + if (HasFailed()) return; + } + + for (size_t i = 0; i < type_parameters.size(); i++) { + if (!inferred_[i]) { + Fail("failed to infer arguments for all type parameters"); + return; + } + } +} + +TypeVector TypeArgumentInference::GetResult() const { + CHECK(!HasFailed()); + TypeVector result(inferred_.size()); + std::transform( + inferred_.begin(), inferred_.end(), result.begin(), + [](base::Optional<const Type*> maybe_type) { return *maybe_type; }); + return result; +} + +void TypeArgumentInference::Match(TypeExpression* parameter, + const Type* argument_type) { + if (BasicTypeExpression* basic = + BasicTypeExpression::DynamicCast(parameter)) { + // If the parameter is referring to one of the type parameters, substitute + if (basic->namespace_qualification.empty() && !basic->is_constexpr) { + auto result = type_parameter_from_name_.find(basic->name); + if (result != type_parameter_from_name_.end()) { + size_t type_parameter_index = result->second; + if (type_parameter_index < num_explicit_) { + return; + } + base::Optional<const Type*>& maybe_inferred = + inferred_[type_parameter_index]; + if (maybe_inferred && *maybe_inferred != argument_type) { + Fail("found conflicting types for generic parameter"); + } else { + inferred_[type_parameter_index] = {argument_type}; + } + return; + } + } + // Try to recurse in case of generic types + if (!basic->generic_arguments.empty()) { + auto* argument_struct_type = StructType::DynamicCast(argument_type); + if (argument_struct_type) { + MatchGeneric(basic, argument_struct_type); + } + } + // NOTE: We could also check whether ground parameter types match the + // argument types, but we are only interested in inferring type arguments + // here + } else { + // TODO(gsps): Perform inference on function and union types + } +} + +void TypeArgumentInference::MatchGeneric(BasicTypeExpression* parameter, + const StructType* argument_type) { + QualifiedName qualified_name{parameter->namespace_qualification, + parameter->name}; + GenericStructType* generic_struct = + Declarations::LookupUniqueGenericStructType(qualified_name); + auto& specialized_from = argument_type->GetSpecializedFrom(); + if (!specialized_from || specialized_from->generic != generic_struct) { + return Fail("found conflicting generic type constructors"); + } + auto& parameters = parameter->generic_arguments; + auto& argument_types = specialized_from->specialized_types; + if (parameters.size() != argument_types.size()) { + Error( + "cannot infer types from generic-struct-typed parameter with " + "incompatible number of arguments") + .Position(parameter->pos) + .Throw(); + } + for (size_t i = 0; i < parameters.size(); i++) { + Match(parameters[i], argument_types[i]); + if (HasFailed()) return; + } +} + +} // namespace torque +} // namespace internal +} // namespace v8 diff --git a/deps/v8/src/torque/type-inference.h b/deps/v8/src/torque/type-inference.h new file mode 100644 index 0000000000..671d68cce5 --- /dev/null +++ b/deps/v8/src/torque/type-inference.h @@ -0,0 +1,84 @@ +// 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_TYPE_INFERENCE_H_ +#define V8_TORQUE_TYPE_INFERENCE_H_ + +#include <string> +#include <unordered_map> + +#include "src/base/optional.h" +#include "src/torque/ast.h" +#include "src/torque/declarations.h" +#include "src/torque/types.h" + +namespace v8 { +namespace internal { +namespace torque { + +// Type argument inference computes a potential instantiation of a generic +// callable given some concrete argument types. As an example, consider the +// generic macro +// +// macro Pick<T: type>(x: T, y: T): T +// +// along with a given call site, such as +// +// Pick(1, 2); +// +// The inference proceeds by matching the term argument types (`constexpr +// int31`, in case of `1` and `2`) against the formal parameter types (`T` in +// both cases). During this matching we discover that `T` must equal `constexpr +// int31`. +// +// The inference will not perform any comprehensive type checking of its own, +// but *does* fail if type parameters cannot be soundly instantiated given the +// call site. For instance, for the following call site +// +// const aSmi: Smi = ...; +// Pick(1, aSmi); // inference fails +// +// inference would fail, since `constexpr int31` is distinct from `Smi`. To +// allow for implicit conversions to be tried in a separate step after type +// argument inference, a number of type arguments may be given explicitly: +// +// Pick<Smi>(1, aSmi); // inference succeeds (doing nothing) +// +// In the above case the inference simply ignores inconsistent constraints on +// `T`. Similarly, we ignore all constraints arising from formal parameters +// that are function- or union-typed. +// +// Finally, note that term parameters are passed as type expressions, since +// we have no way of expressing a reference to type parameter as a Type. These +// type expressions are resolved during matching, so TypeArgumentInference +// should be instantiated in the appropriate scope. +class TypeArgumentInference { + public: + TypeArgumentInference(const NameVector& type_parameters, + const TypeVector& explicit_type_arguments, + const std::vector<TypeExpression*>& term_parameters, + const TypeVector& term_argument_types); + + bool HasFailed() const { return failure_reason_.has_value(); } + const char* GetFailureReason() { return *failure_reason_; } + TypeVector GetResult() const; + + private: + void Fail(const char* reason) { failure_reason_ = {reason}; } + + void Match(TypeExpression* parameter, const Type* argument_type); + void MatchGeneric(BasicTypeExpression* parameter, + const StructType* argument_type); + + size_t num_explicit_; + std::unordered_map<std::string, size_t> type_parameter_from_name_; + std::vector<base::Optional<const Type*>> inferred_; + base::Optional<const char*> failure_reason_; +}; + +} // namespace torque +} // namespace internal +} // namespace v8 + +#endif // V8_TORQUE_TYPE_INFERENCE_H_ diff --git a/deps/v8/src/torque/type-oracle.cc b/deps/v8/src/torque/type-oracle.cc index 47331543fc..c7e11c2165 100644 --- a/deps/v8/src/torque/type-oracle.cc +++ b/deps/v8/src/torque/type-oracle.cc @@ -3,6 +3,7 @@ // found in the LICENSE file. #include "src/torque/type-oracle.h" +#include "src/torque/type-visitor.h" namespace v8 { namespace internal { @@ -23,6 +24,28 @@ void TypeOracle::FinalizeAggregateTypes() { } } +// static +const StructType* TypeOracle::GetGenericStructTypeInstance( + GenericStructType* generic_struct, TypeVector arg_types) { + auto& params = generic_struct->generic_parameters(); + auto& specializations = generic_struct->specializations(); + + if (params.size() != arg_types.size()) { + ReportError("Generic struct takes ", params.size(), " parameters, but ", + arg_types.size(), " were given"); + } + + if (auto specialization = specializations.Get(arg_types)) { + return *specialization; + } else { + CurrentScope::Scope generic_scope(generic_struct->ParentScope()); + auto struct_type = TypeVisitor::ComputeType(generic_struct->declaration(), + {{generic_struct, arg_types}}); + specializations.Add(arg_types, struct_type); + return struct_type; + } +} + } // namespace torque } // namespace internal } // namespace v8 diff --git a/deps/v8/src/torque/type-oracle.h b/deps/v8/src/torque/type-oracle.h index 405cb41e75..643c78c030 100644 --- a/deps/v8/src/torque/type-oracle.h +++ b/deps/v8/src/torque/type-oracle.h @@ -30,9 +30,13 @@ class TypeOracle : public ContextualClass<TypeOracle> { return result; } - static StructType* GetStructType(const std::string& name) { - StructType* result = new StructType(CurrentNamespace(), name); + static StructType* GetStructType( + const StructDeclaration* decl, + StructType::MaybeSpecializationKey specialized_from) { + Namespace* nspace = new Namespace(STRUCT_NAMESPACE_STRING); + StructType* result = new StructType(nspace, decl, specialized_from); Get().aggregate_types_.push_back(std::unique_ptr<StructType>(result)); + Get().struct_namespaces_.push_back(std::unique_ptr<Namespace>(nspace)); return result; } @@ -60,8 +64,26 @@ class TypeOracle : public ContextualClass<TypeOracle> { return result; } - static const ReferenceType* GetReferenceType(const Type* referenced_type) { - return Get().reference_types_.Add(ReferenceType(referenced_type)); + static const StructType* GetGenericStructTypeInstance( + GenericStructType* generic_struct, TypeVector arg_types); + + static GenericStructType* GetReferenceGeneric() { + return Declarations::LookupUniqueGenericStructType(QualifiedName( + {TORQUE_INTERNAL_NAMESPACE_STRING}, REFERENCE_TYPE_STRING)); + } + + static GenericStructType* GetSliceGeneric() { + return Declarations::LookupUniqueGenericStructType( + QualifiedName({TORQUE_INTERNAL_NAMESPACE_STRING}, SLICE_TYPE_STRING)); + } + + static const StructType* GetReferenceType(const Type* referenced_type) { + return GetGenericStructTypeInstance(GetReferenceGeneric(), + {referenced_type}); + } + + static const StructType* GetSliceType(const Type* referenced_type) { + return GetGenericStructTypeInstance(GetSliceGeneric(), {referenced_type}); } static const std::vector<const BuiltinPointerType*>& @@ -131,6 +153,10 @@ class TypeOracle : public ContextualClass<TypeOracle> { return Get().GetBuiltinType(HEAP_OBJECT_TYPE_STRING); } + static const Type* GetJSAnyType() { + return Get().GetBuiltinType(JSANY_TYPE_STRING); + } + static const Type* GetJSObjectType() { return Get().GetBuiltinType(JSOBJECT_TYPE_STRING); } @@ -245,10 +271,10 @@ class TypeOracle : public ContextualClass<TypeOracle> { Deduplicator<BuiltinPointerType> function_pointer_types_; std::vector<const BuiltinPointerType*> all_builtin_pointer_types_; Deduplicator<UnionType> union_types_; - Deduplicator<ReferenceType> reference_types_; std::vector<std::unique_ptr<Type>> nominal_types_; std::vector<std::unique_ptr<AggregateType>> aggregate_types_; std::vector<std::unique_ptr<Type>> top_types_; + std::vector<std::unique_ptr<Namespace>> struct_namespaces_; }; } // namespace torque diff --git a/deps/v8/src/torque/type-visitor.cc b/deps/v8/src/torque/type-visitor.cc index 37be0df006..9b5c96ee40 100644 --- a/deps/v8/src/torque/type-visitor.cc +++ b/deps/v8/src/torque/type-visitor.cc @@ -8,6 +8,7 @@ #include "src/torque/declarable.h" #include "src/torque/global-context.h" #include "src/torque/server-data.h" +#include "src/torque/type-inference.h" #include "src/torque/type-oracle.h" namespace v8 { @@ -91,49 +92,47 @@ 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()); + TorqueMacroDeclaration::DynamicCast(declaration); + Signature signature = TypeVisitor::MakeSignature(method); 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); + Statement* body = *(method->body); + const std::string& method_name(method->name->value); signature.parameter_types.types.insert( signature.parameter_types.types.begin() + signature.implicit_count, container_type); - Declarations::CreateMethod(container_type, method_name, signature, false, - body); + Declarations::CreateMethod(container_type, method_name, signature, body); } } -namespace { -std::string ComputeStructName(StructDeclaration* decl) { - TypeVector args; - if (decl->IsGeneric()) { - args.resize(decl->generic_parameters.size()); - std::transform( - decl->generic_parameters.begin(), decl->generic_parameters.end(), - args.begin(), [](Identifier* parameter) { - return Declarations::LookupTypeAlias(QualifiedName(parameter->value)) - ->type(); - }); +const StructType* TypeVisitor::ComputeType( + StructDeclaration* decl, + StructType::MaybeSpecializationKey specialized_from) { + StructType* struct_type = TypeOracle::GetStructType(decl, specialized_from); + CurrentScope::Scope struct_namespace_scope(struct_type->nspace()); + CurrentSourcePosition::Scope position_activator(decl->pos); + + if (specialized_from) { + auto& params = specialized_from->generic->generic_parameters(); + auto arg_types_iterator = specialized_from->specialized_types.begin(); + for (auto param : params) { + TypeAlias* alias = Declarations::DeclareType(param, *arg_types_iterator); + alias->SetIsUserDefined(false); + arg_types_iterator++; + } } - return StructType::ComputeName(decl->name->value, args); -} -} // namespace -const StructType* TypeVisitor::ComputeType(StructDeclaration* decl) { - CurrentSourcePosition::Scope position_activator(decl->pos); - StructType* struct_type = TypeOracle::GetStructType(ComputeStructName(decl)); 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); + if (field_type->IsConstexpr()) { + ReportError("struct field \"", field.name_and_type.name->value, + "\" carries constexpr type \"", *field_type, "\""); + } struct_type->RegisterField({field.name_and_type.name->pos, struct_type, base::nullopt, @@ -144,7 +143,6 @@ const StructType* TypeVisitor::ComputeType(StructDeclaration* decl) { false}); offset += LoweredSlotCount(field_type); } - DeclareMethods(struct_type, decl->methods); return struct_type; } @@ -214,34 +212,8 @@ const Type* TypeVisitor::ComputeType(TypeExpression* type_expression) { } else { auto* generic_struct = Declarations::LookupUniqueGenericStructType(qualified_name); - auto& params = generic_struct->generic_parameters(); - auto& specializations = generic_struct->specializations(); - if (params.size() != args.size()) { - ReportError("Generic struct takes ", params.size(), - " parameters, but only ", args.size(), " were given"); - } - - std::vector<const Type*> arg_types = ComputeTypeVector(args); - if (auto specialization = specializations.Get(arg_types)) { - type = *specialization; - } else { - CurrentScope::Scope generic_scope(generic_struct->ParentScope()); - // Create a temporary fake-namespace just to temporarily declare the - // specialization aliases for the generic types to create a signature. - Namespace tmp_namespace("_tmp"); - CurrentScope::Scope tmp_namespace_scope(&tmp_namespace); - auto arg_types_iterator = arg_types.begin(); - for (auto param : params) { - TypeAlias* alias = - Declarations::DeclareType(param, *arg_types_iterator); - alias->SetIsUserDefined(false); - arg_types_iterator++; - } - - auto struct_type = ComputeType(generic_struct->declaration()); - specializations.Add(arg_types, struct_type); - type = struct_type; - } + type = TypeOracle::GetGenericStructTypeInstance(generic_struct, + ComputeTypeVector(args)); pos = generic_struct->declaration()->name->pos; } @@ -254,10 +226,6 @@ const Type* TypeVisitor::ComputeType(TypeExpression* type_expression) { 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; @@ -269,22 +237,23 @@ const Type* TypeVisitor::ComputeType(TypeExpression* type_expression) { } } -Signature TypeVisitor::MakeSignature(const CallableNodeSignature* signature) { +Signature TypeVisitor::MakeSignature(const CallableDeclaration* declaration) { LabelDeclarationVector definition_vector; - for (const auto& label : signature->labels) { + for (const auto& label : declaration->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, + if (declaration->parameters.has_varargs) + arguments_variable = declaration->parameters.arguments_variable; + Signature result{declaration->parameters.names, arguments_variable, - {ComputeTypeVector(signature->parameters.types), - signature->parameters.has_varargs}, - signature->parameters.implicit_count, - ComputeType(signature->return_type), - definition_vector}; + {ComputeTypeVector(declaration->parameters.types), + declaration->parameters.has_varargs}, + declaration->parameters.implicit_count, + ComputeType(declaration->return_type), + definition_vector, + declaration->transitioning}; return result; } @@ -345,7 +314,8 @@ void TypeVisitor::VisitClassFieldsAndMethods( std::string machine_type; std::tie(field_size, size_string) = field.GetFieldSizeInformation(); // Our allocations don't support alignments beyond kTaggedSize. - size_t alignment = std::min(size_t{kTaggedSize}, field_size); + size_t alignment = std::min( + static_cast<size_t>(TargetArchitecture::TaggedSize()), field_size); if (alignment > 0 && class_offset % alignment != 0) { ReportError("field ", field_expression.name_and_type.name, " at offset ", class_offset, " is not ", alignment, @@ -359,6 +329,60 @@ void TypeVisitor::VisitClassFieldsAndMethods( DeclareMethods(class_type, class_declaration->methods); } +void TypeVisitor::VisitStructMethods( + StructType* struct_type, const StructDeclaration* struct_declaration) { + DeclareMethods(struct_type, struct_declaration->methods); +} + +const StructType* TypeVisitor::ComputeTypeForStructExpression( + TypeExpression* type_expression, + const std::vector<const Type*>& term_argument_types) { + auto* basic = BasicTypeExpression::DynamicCast(type_expression); + if (!basic) { + ReportError("expected basic type expression referring to struct"); + } + + QualifiedName qualified_name{basic->namespace_qualification, basic->name}; + base::Optional<GenericStructType*> maybe_generic_struct = + Declarations::TryLookupGenericStructType(qualified_name); + + // Compute types of non-generic structs as usual + if (!maybe_generic_struct) { + const Type* type = ComputeType(type_expression); + const StructType* struct_type = StructType::DynamicCast(type); + if (!struct_type) { + ReportError(*type, " is not a struct, but used like one"); + } + return struct_type; + } + + auto generic_struct = *maybe_generic_struct; + auto explicit_type_arguments = ComputeTypeVector(basic->generic_arguments); + + std::vector<TypeExpression*> term_parameters; + auto& fields = generic_struct->declaration()->fields; + term_parameters.reserve(fields.size()); + for (auto& field : fields) { + term_parameters.push_back(field.name_and_type.type); + } + + CurrentScope::Scope generic_scope(generic_struct->ParentScope()); + TypeArgumentInference inference( + generic_struct->declaration()->generic_parameters, + explicit_type_arguments, term_parameters, term_argument_types); + + if (inference.HasFailed()) { + ReportError("failed to infer type arguments for struct ", basic->name, + " initialization: ", inference.GetFailureReason()); + } + if (GlobalContext::collect_language_server_data()) { + LanguageServerData::AddDefinition(type_expression->pos, + generic_struct->declaration()->name->pos); + } + return TypeOracle::GetGenericStructTypeInstance(generic_struct, + inference.GetResult()); +} + } // namespace torque } // namespace internal } // namespace v8 diff --git a/deps/v8/src/torque/type-visitor.h b/deps/v8/src/torque/type-visitor.h index 93de02b860..cafd752cbf 100644 --- a/deps/v8/src/torque/type-visitor.h +++ b/deps/v8/src/torque/type-visitor.h @@ -27,14 +27,22 @@ class TypeVisitor { static const Type* ComputeType(TypeExpression* type_expression); static void VisitClassFieldsAndMethods( ClassType* class_type, const ClassDeclaration* class_declaration); - static Signature MakeSignature(const CallableNodeSignature* signature); + static void VisitStructMethods(StructType* struct_type, + const StructDeclaration* struct_declaration); + static Signature MakeSignature(const CallableDeclaration* declaration); + static const StructType* ComputeTypeForStructExpression( + TypeExpression* type_expression, + const std::vector<const Type*>& term_argument_types); private: friend class TypeAlias; + friend class TypeOracle; 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 StructType* ComputeType( + StructDeclaration* decl, + StructType::MaybeSpecializationKey specialized_from = base::nullopt); static const ClassType* ComputeType(ClassDeclaration* decl); }; diff --git a/deps/v8/src/torque/types.cc b/deps/v8/src/torque/types.cc index 37a328b1dc..fe792401f6 100644 --- a/deps/v8/src/torque/types.cc +++ b/deps/v8/src/torque/types.cc @@ -4,9 +4,9 @@ #include <iostream> -#include "src/common/globals.h" #include "src/torque/ast.h" #include "src/torque/declarable.h" +#include "src/torque/global-context.h" #include "src/torque/type-oracle.h" #include "src/torque/type-visitor.h" #include "src/torque/types.h" @@ -263,7 +263,7 @@ const Field& AggregateType::LookupFieldInternal(const std::string& name) const { return parent_class->LookupField(name); } } - ReportError("no field ", name, " found"); + ReportError("no field ", name, " found in ", this->ToString()); } const Field& AggregateType::LookupField(const std::string& name) const { @@ -276,13 +276,14 @@ std::string StructType::GetGeneratedTypeNameImpl() const { } // static -std::string StructType::ComputeName(const std::string& basename, - const std::vector<const Type*>& args) { - if (args.size() == 0) return basename; +std::string StructType::ComputeName( + const std::string& basename, + StructType::MaybeSpecializationKey specialized_from) { + if (!specialized_from) return basename; std::stringstream s; s << basename << "<"; bool first = true; - for (auto t : args) { + for (auto t : specialized_from->specialized_types) { if (!first) { s << ", "; } @@ -293,6 +294,43 @@ std::string StructType::ComputeName(const std::string& basename, return s.str(); } +std::string StructType::MangledName() const { + std::stringstream result; + // TODO(gsps): Add 'ST' as a prefix once we can control the generated type + // name from Torque code + result << decl_->name->value; + if (specialized_from_) { + for (const Type* t : specialized_from_->specialized_types) { + std::string arg_type_string = t->MangledName(); + result << arg_type_string.size() << arg_type_string; + } + } + return result.str(); +} + +// static +base::Optional<const Type*> StructType::MatchUnaryGeneric( + const Type* type, GenericStructType* generic) { + if (auto* struct_type = StructType::DynamicCast(type)) { + return MatchUnaryGeneric(struct_type, generic); + } + return base::nullopt; +} + +// static +base::Optional<const Type*> StructType::MatchUnaryGeneric( + const StructType* type, GenericStructType* generic) { + DCHECK_EQ(generic->generic_parameters().size(), 1); + if (!type->specialized_from_) { + return base::nullopt; + } + auto& key = type->specialized_from_.value(); + if (key.generic != generic || key.specialized_types.size() != 1) { + return base::nullopt; + } + return {key.specialized_types[0]}; +} + std::vector<Method*> AggregateType::Methods(const std::string& name) const { if (!is_finalized_) Finalize(); std::vector<Method*> result; @@ -307,6 +345,17 @@ std::string StructType::ToExplicitString() const { return result.str(); } +void StructType::Finalize() const { + if (is_finalized_) return; + { + CurrentScope::Scope scope_activator(nspace()); + CurrentSourcePosition::Scope position_activator(decl_->pos); + TypeVisitor::VisitStructMethods(const_cast<StructType*>(this), decl_); + } + is_finalized_ = true; + CheckForDuplicateFields(); +} + constexpr ClassFlags ClassType::kInternalFlags; ClassType::ClassType(const Type* parent, Namespace* nspace, @@ -380,6 +429,17 @@ void ClassType::Finalize() const { CheckForDuplicateFields(); } +std::vector<Field> ClassType::ComputeAllFields() const { + std::vector<Field> all_fields; + const ClassType* super_class = this->GetSuperClass(); + if (super_class) { + all_fields = super_class->ComputeAllFields(); + } + const std::vector<Field>& fields = this->fields(); + all_fields.insert(all_fields.end(), fields.begin(), fields.end()); + return all_fields; +} + void ClassType::GenerateAccessors() { // For each field, construct AST snippets that implement a CSA accessor // function and define a corresponding '.field' operator. The @@ -404,8 +464,7 @@ void ClassType::GenerateAccessors() { MakeNode<ReturnStatement>(MakeNode<FieldAccessExpression>( parameter, MakeNode<Identifier>(field.name_and_type.name))); Declarations::DeclareMacro(load_macro_name, true, base::nullopt, - load_signature, false, load_body, base::nullopt, - false); + load_signature, load_body, base::nullopt); // Store accessor IdentifierExpression* value = MakeNode<IdentifierExpression>( @@ -425,8 +484,8 @@ void ClassType::GenerateAccessors() { parameter, MakeNode<Identifier>(field.name_and_type.name)), value)); Declarations::DeclareMacro(store_macro_name, true, base::nullopt, - store_signature, false, store_body, - base::nullopt, false); + store_signature, store_body, base::nullopt, + false); } } @@ -560,9 +619,6 @@ void AppendLoweredTypes(const Type* type, std::vector<const Type*>* result) { for (const Field& field : s->fields()) { AppendLoweredTypes(field.name_and_type.type, result); } - } else if (type->IsReferenceType()) { - result->push_back(TypeOracle::GetHeapObjectType()); - result->push_back(TypeOracle::GetIntPtrType()); } else { result->push_back(type); } @@ -606,10 +662,10 @@ std::tuple<size_t, std::string> Field::GetFieldSizeInformation() const { const Type* field_type = this->name_and_type.type; size_t field_size = 0; if (field_type->IsSubtypeOf(TypeOracle::GetTaggedType())) { - field_size = kTaggedSize; + field_size = TargetArchitecture::TaggedSize(); size_string = "kTaggedSize"; } else if (field_type->IsSubtypeOf(TypeOracle::GetRawPtrType())) { - field_size = kSystemPointerSize; + field_size = TargetArchitecture::RawPtrSize(); size_string = "kSystemPointerSize"; } else if (field_type->IsSubtypeOf(TypeOracle::GetVoidType())) { field_size = 0; @@ -636,10 +692,10 @@ std::tuple<size_t, std::string> Field::GetFieldSizeInformation() const { field_size = kDoubleSize; size_string = "kDoubleSize"; } else if (field_type->IsSubtypeOf(TypeOracle::GetIntPtrType())) { - field_size = kIntptrSize; + field_size = TargetArchitecture::RawPtrSize(); size_string = "kIntptrSize"; } else if (field_type->IsSubtypeOf(TypeOracle::GetUIntPtrType())) { - field_size = kIntptrSize; + field_size = TargetArchitecture::RawPtrSize(); size_string = "kIntptrSize"; } else { ReportError("fields of type ", *field_type, " are not (yet) supported"); diff --git a/deps/v8/src/torque/types.h b/deps/v8/src/torque/types.h index f6180c4250..d2198d50c3 100644 --- a/deps/v8/src/torque/types.h +++ b/deps/v8/src/torque/types.h @@ -25,6 +25,7 @@ class AggregateType; struct Identifier; class Macro; class Method; +class GenericStructType; class StructType; class ClassType; class Value; @@ -36,7 +37,6 @@ class TypeBase { kTopType, kAbstractType, kBuiltinPointerType, - kReferenceType, kUnionType, kStructType, kClassType @@ -47,7 +47,6 @@ class TypeBase { bool IsBuiltinPointerType() const { return kind() == Kind::kBuiltinPointerType; } - bool IsReferenceType() const { return kind() == Kind::kReferenceType; } bool IsUnionType() const { return kind() == Kind::kUnionType; } bool IsStructType() const { return kind() == Kind::kStructType; } bool IsClassType() const { return kind() == Kind::kClassType; } @@ -143,6 +142,12 @@ struct NameAndType { std::ostream& operator<<(std::ostream& os, const NameAndType& name_and_type); +template <typename T> +struct SpecializationKey { + T* generic; + TypeVector specialized_types; +}; + struct Field { // TODO(danno): This likely should be refactored, the handling of the types // using the universal grab-bag utility with std::tie, as well as the @@ -298,43 +303,6 @@ class V8_EXPORT_PRIVATE BuiltinPointerType final : public Type { const size_t function_pointer_type_id_; }; -class ReferenceType final : public Type { - public: - DECLARE_TYPE_BOILERPLATE(ReferenceType) - std::string MangledName() const override { - return "RT" + referenced_type_->MangledName(); - } - std::string ToExplicitString() const override { - std::string s = referenced_type_->ToString(); - if (s.find(' ') != std::string::npos) { - s = "(" + s + ")"; - } - return "&" + s; - } - std::string GetGeneratedTypeNameImpl() const override { - return "CodeStubAssembler::Reference"; - } - std::string GetGeneratedTNodeTypeNameImpl() const override { UNREACHABLE(); } - - const Type* referenced_type() const { return referenced_type_; } - - friend size_t hash_value(const ReferenceType& p) { - return base::hash_combine(static_cast<size_t>(Kind::kReferenceType), - p.referenced_type_); - } - bool operator==(const ReferenceType& other) const { - return referenced_type_ == other.referenced_type_; - } - - private: - friend class TypeOracle; - explicit ReferenceType(const Type* referenced_type) - : Type(Kind::kReferenceType, nullptr), - referenced_type_(referenced_type) {} - - const Type* const referenced_type_; -}; - bool operator<(const Type& a, const Type& b); struct TypeLess { bool operator()(const Type* const a, const Type* const b) const { @@ -500,32 +468,38 @@ class AggregateType : public Type { class StructType final : public AggregateType { public: DECLARE_TYPE_BOILERPLATE(StructType) + + using MaybeSpecializationKey = + base::Optional<SpecializationKey<GenericStructType>>; + std::string ToExplicitString() const override; std::string GetGeneratedTypeNameImpl() const override; - std::string MangledName() const override { - // TODO(gsps): Generate more readable mangled names - std::string str(name()); - std::replace(str.begin(), str.end(), ',', '_'); - std::replace(str.begin(), str.end(), ' ', '_'); - std::replace(str.begin(), str.end(), '<', '_'); - std::replace(str.begin(), str.end(), '>', '_'); - return str; + std::string MangledName() const override; + const MaybeSpecializationKey& GetSpecializedFrom() const { + return specialized_from_; } - static std::string ComputeName(const std::string& basename, - const std::vector<const Type*>& args); + static base::Optional<const Type*> MatchUnaryGeneric( + const Type* type, GenericStructType* generic); + static base::Optional<const Type*> MatchUnaryGeneric( + const StructType* type, GenericStructType* generic); private: friend class TypeOracle; - StructType(Namespace* nspace, const std::string& name) - : AggregateType(Kind::kStructType, nullptr, nspace, name) {} + StructType(Namespace* nspace, const StructDeclaration* decl, + MaybeSpecializationKey specialized_from = base::nullopt) + : AggregateType(Kind::kStructType, nullptr, nspace, + ComputeName(decl->name->value, specialized_from)), + decl_(decl), + specialized_from_(specialized_from) {} - void Finalize() const override { - is_finalized_ = true; - CheckForDuplicateFields(); - } + void Finalize() const override; + + static std::string ComputeName(const std::string& basename, + MaybeSpecializationKey specialized_from); - const std::string& GetStructName() const { return name(); } + const StructDeclaration* decl_; + MaybeSpecializationKey specialized_from_; }; class TypeAlias; @@ -573,6 +547,8 @@ class ClassType final : public AggregateType { } void Finalize() const override; + std::vector<Field> ComputeAllFields() const; + private: friend class TypeOracle; friend class TypeVisitor; @@ -668,22 +644,25 @@ using NameVector = std::vector<Identifier*>; struct Signature { Signature(NameVector n, base::Optional<std::string> arguments_variable, - ParameterTypes p, size_t i, const Type* r, LabelDeclarationVector l) + ParameterTypes p, size_t i, const Type* r, LabelDeclarationVector l, + bool transitioning) : parameter_names(std::move(n)), arguments_variable(arguments_variable), parameter_types(std::move(p)), implicit_count(i), return_type(r), - labels(std::move(l)) {} - Signature() : implicit_count(0), return_type(nullptr) {} + labels(std::move(l)), + transitioning(transitioning) {} + Signature() = default; const TypeVector& types() const { return parameter_types.types; } NameVector parameter_names; base::Optional<std::string> arguments_variable; ParameterTypes parameter_types; - size_t implicit_count; + size_t implicit_count = 0; size_t ExplicitCount() const { return types().size() - implicit_count; } const Type* return_type; LabelDeclarationVector labels; + bool transitioning = false; bool HasSameTypesAs( const Signature& other, ParameterMode mode = ParameterMode::kProcessImplicit) const; diff --git a/deps/v8/src/torque/utils.cc b/deps/v8/src/torque/utils.cc index 244d1587db..38862b31b0 100644 --- a/deps/v8/src/torque/utils.cc +++ b/deps/v8/src/torque/utils.cc @@ -168,9 +168,9 @@ bool IsKeywordLikeName(const std::string& s) { // naming convention and are those exempt from the normal type convention. bool IsMachineType(const std::string& s) { static const char* const machine_types[]{ - "void", "never", "int8", "uint8", "int16", "uint16", - "int31", "uint31", "int32", "uint32", "int64", "intptr", - "uintptr", "float32", "float64", "bool", "string", "bint"}; + "void", "never", "int8", "uint8", "int16", "uint16", "int31", + "uint31", "int32", "uint32", "int64", "intptr", "uintptr", "float32", + "float64", "bool", "string", "bint", "char8", "char16"}; return std::find(std::begin(machine_types), std::end(machine_types), s) != std::end(machine_types); @@ -292,6 +292,42 @@ void ReplaceFileContentsIfDifferent(const std::string& file_path, } } +IfDefScope::IfDefScope(std::ostream& os, std::string d) + : os_(os), d_(std::move(d)) { + os_ << "#ifdef " << d_ << "\n"; +} +IfDefScope::~IfDefScope() { os_ << "#endif // " << d_ << "\n"; } + +NamespaceScope::NamespaceScope(std::ostream& os, + std::initializer_list<std::string> namespaces) + : os_(os), d_(std::move(namespaces)) { + for (const std::string& s : d_) { + os_ << "namespace " << s << " {\n"; + } +} +NamespaceScope::~NamespaceScope() { + for (auto i = d_.rbegin(); i != d_.rend(); ++i) { + os_ << "} // namespace " << *i << "\n"; + } +} + +IncludeGuardScope::IncludeGuardScope(std::ostream& os, std::string file_name) + : os_(os), + d_("V8_GEN_TORQUE_GENERATED_" + CapifyStringWithUnderscores(file_name) + + "_") { + os_ << "#ifndef " << d_ << "\n"; + os_ << "#define " << d_ << "\n\n"; +} +IncludeGuardScope::~IncludeGuardScope() { os_ << "#endif // " << d_ << "\n"; } + +IncludeObjectMacrosScope::IncludeObjectMacrosScope(std::ostream& os) : os_(os) { + os_ << "\n// Has to be the last include (doesn't have include guards):\n" + "#include \"src/objects/object-macros.h\"\n"; +} +IncludeObjectMacrosScope::~IncludeObjectMacrosScope() { + os_ << "\n#include \"src/objects/object-macros-undef.h\"\n"; +} + } // namespace torque } // namespace internal } // namespace v8 diff --git a/deps/v8/src/torque/utils.h b/deps/v8/src/torque/utils.h index fb4ad59f99..5f44dedea9 100644 --- a/deps/v8/src/torque/utils.h +++ b/deps/v8/src/torque/utils.h @@ -292,7 +292,7 @@ T* CheckNotNull(T* x) { } template <class T> -inline std::ostream& operator<<(std::ostream& os, Stack<T>& t) { +inline std::ostream& operator<<(std::ostream& os, const Stack<T>& t) { os << "Stack{"; PrintCommaSeparatedList(os, t); os << "}"; @@ -356,6 +356,54 @@ inline bool StringEndsWith(const std::string& s, const std::string& suffix) { return s.substr(s.size() - suffix.size()) == suffix; } +class IfDefScope { + public: + IfDefScope(std::ostream& os, std::string d); + ~IfDefScope(); + + private: + IfDefScope(const IfDefScope&) = delete; + IfDefScope& operator=(const IfDefScope&) = delete; + std::ostream& os_; + std::string d_; +}; + +class NamespaceScope { + public: + NamespaceScope(std::ostream& os, + std::initializer_list<std::string> namespaces); + ~NamespaceScope(); + + private: + NamespaceScope(const NamespaceScope&) = delete; + NamespaceScope& operator=(const NamespaceScope&) = delete; + std::ostream& os_; + std::vector<std::string> d_; +}; + +class IncludeGuardScope { + public: + IncludeGuardScope(std::ostream& os, std::string file_name); + ~IncludeGuardScope(); + + private: + IncludeGuardScope(const IncludeGuardScope&) = delete; + IncludeGuardScope& operator=(const IncludeGuardScope&) = delete; + std::ostream& os_; + std::string d_; +}; + +class IncludeObjectMacrosScope { + public: + explicit IncludeObjectMacrosScope(std::ostream& os); + ~IncludeObjectMacrosScope(); + + private: + IncludeObjectMacrosScope(const IncludeObjectMacrosScope&) = delete; + IncludeObjectMacrosScope& operator=(const IncludeObjectMacrosScope&) = delete; + std::ostream& os_; +}; + } // namespace torque } // namespace internal } // namespace v8 |