[torque] Replace ReferenceType by generic Torque struct Reference<T>
This CL removes the built-in reference type in favor of a Torque-implemented generic struct, i.e., internal::Reference<T>. It also adds various infrastructure for getting and creating new generic struct instances, as well as matching against them. R=tebbi@chromium.org Change-Id: I1e3d6afe355a0603fa9c3ad789c6b8a97d1b3c26 Reviewed-on: https://chromium-review.googlesource.com/c/v8/v8/+/1718148 Commit-Queue: Georg Schmid <gsps@google.com> Reviewed-by: Tobias Tebbi <tebbi@chromium.org> Cr-Commit-Position: refs/heads/master@{#62939}
This commit is contained in:
parent
0a424ac1a5
commit
35a613555c
1
BUILD.gn
1
BUILD.gn
@ -984,6 +984,7 @@ torque_files = [
|
||||
"src/builtins/string-slice.tq",
|
||||
"src/builtins/string-startswith.tq",
|
||||
"src/builtins/string-substring.tq",
|
||||
"src/builtins/torque-internal.tq",
|
||||
"src/builtins/typed-array-createtypedarray.tq",
|
||||
"src/builtins/typed-array-every.tq",
|
||||
"src/builtins/typed-array-filter.tq",
|
||||
|
12
src/builtins/torque-internal.tq
Normal file
12
src/builtins/torque-internal.tq
Normal file
@ -0,0 +1,12 @@
|
||||
// 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.
|
||||
|
||||
namespace torque_internal {
|
||||
|
||||
struct Reference<T: type> {
|
||||
const object: HeapObject;
|
||||
const offset: intptr;
|
||||
}
|
||||
|
||||
} // namespace torque_internal
|
@ -847,6 +847,7 @@ class V8_EXPORT_PRIVATE CodeStubAssembler
|
||||
|
||||
// Reference is the CSA-equivalent of a Torque reference value,
|
||||
// representing an inner pointer into a HeapObject.
|
||||
// TODO(gsps): Remove in favor of flattened {Load,Store}Reference interface
|
||||
struct Reference {
|
||||
TNode<HeapObject> object;
|
||||
TNode<IntPtrT> offset;
|
||||
|
@ -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) \
|
||||
@ -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)
|
||||
|
@ -49,6 +49,8 @@ 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";
|
||||
|
||||
inline bool IsConstexprName(const std::string& name) {
|
||||
return name.substr(0, std::strlen(CONSTEXPR_TYPE_PREFIX)) ==
|
||||
|
@ -305,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);
|
||||
@ -766,11 +765,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()
|
||||
|
@ -74,11 +74,7 @@ base::Optional<const Type*> InferTypeArgument(const std::string& to_infer,
|
||||
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());
|
||||
}
|
||||
// TODO(gsps): Perform type inference for generic types
|
||||
return base::nullopt;
|
||||
}
|
||||
|
||||
|
@ -505,11 +505,6 @@ class Generic : public Declarable {
|
||||
SpecializationMap<Callable> specializations_;
|
||||
};
|
||||
|
||||
struct SpecializationKey {
|
||||
Generic* generic;
|
||||
TypeVector specialized_types;
|
||||
};
|
||||
|
||||
class GenericStructType : public Declarable {
|
||||
public:
|
||||
DECLARE_DECLARABLE_BOILERPLATE(GenericStructType, generic_type)
|
||||
|
@ -205,7 +205,7 @@ void DeclarationVisitor::Visit(SpecializationDeclaration* decl) {
|
||||
TypeVisitor::MakeSignature(decl->signature.get());
|
||||
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 +233,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,8 +245,9 @@ void DeclarationVisitor::Visit(SpecializationDeclaration* decl) {
|
||||
matching_generic->IdentifierPosition());
|
||||
}
|
||||
|
||||
Specialize(SpecializationKey{matching_generic, TypeVisitor::ComputeTypeVector(
|
||||
decl->generic_parameters)},
|
||||
Specialize(SpecializationKey<Generic>{matching_generic,
|
||||
TypeVisitor::ComputeTypeVector(
|
||||
decl->generic_parameters)},
|
||||
matching_generic->declaration()->callable, decl->signature.get(),
|
||||
decl->body, decl->pos);
|
||||
}
|
||||
@ -267,7 +268,8 @@ 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();
|
||||
@ -288,7 +290,7 @@ void DeclarationVisitor::DeclareSpecializedTypes(const SpecializationKey& key) {
|
||||
}
|
||||
|
||||
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.
|
||||
@ -299,7 +301,8 @@ Signature DeclarationVisitor::MakeSpecializedSignature(
|
||||
key.generic->declaration()->callable->signature.get());
|
||||
}
|
||||
|
||||
Callable* DeclarationVisitor::SpecializeImplicit(const SpecializationKey& key) {
|
||||
Callable* DeclarationVisitor::SpecializeImplicit(
|
||||
const SpecializationKey<Generic>& key) {
|
||||
if (!key.generic->declaration()->body &&
|
||||
IntrinsicDeclaration::DynamicCast(key.generic->declaration()->callable) ==
|
||||
nullptr) {
|
||||
@ -318,7 +321,7 @@ Callable* DeclarationVisitor::SpecializeImplicit(const SpecializationKey& key) {
|
||||
}
|
||||
|
||||
Callable* DeclarationVisitor::Specialize(
|
||||
const SpecializationKey& key, CallableNode* declaration,
|
||||
const SpecializationKey<Generic>& key, CallableNode* declaration,
|
||||
base::Optional<const CallableNodeSignature*> signature,
|
||||
base::Optional<Statement*> body, SourcePosition position) {
|
||||
CurrentSourcePosition::Scope pos_scope(position);
|
||||
|
@ -107,15 +107,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,
|
||||
const SpecializationKey<Generic>& key, CallableNode* declaration,
|
||||
base::Optional<const CallableNodeSignature*> signature,
|
||||
base::Optional<Statement*> body, SourcePosition position);
|
||||
|
||||
private:
|
||||
static void DeclareSpecializedTypes(const SpecializationKey& key);
|
||||
static void DeclareSpecializedTypes(const SpecializationKey<Generic>& key);
|
||||
};
|
||||
|
||||
} // namespace torque
|
||||
|
@ -1599,7 +1599,7 @@ void FailCallableLookup(const std::string& reason, const QualifiedName& name,
|
||||
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;
|
||||
@ -1664,7 +1664,8 @@ Callable* ImplementationVisitor::LookupCallable(
|
||||
overloads.push_back(generic);
|
||||
overload_signatures.push_back(
|
||||
DeclarationVisitor::MakeSpecializedSignature(
|
||||
SpecializationKey{generic, *inferred_specialization_types}));
|
||||
SpecializationKey<Generic>{generic,
|
||||
*inferred_specialization_types}));
|
||||
} else if (Callable* callable = Callable::DynamicCast(declarable)) {
|
||||
overloads.push_back(callable);
|
||||
overload_signatures.push_back(callable->signature());
|
||||
@ -1717,9 +1718,9 @@ Callable* ImplementationVisitor::LookupCallable(
|
||||
}
|
||||
|
||||
if (Generic* generic = Generic::DynamicCast(overloads[best])) {
|
||||
result = GetOrCreateSpecialization(
|
||||
SpecializationKey{generic, *generic->InferSpecializationTypes(
|
||||
specialization_types, parameter_types)});
|
||||
result = GetOrCreateSpecialization(SpecializationKey<Generic>{
|
||||
generic, *generic->InferSpecializationTypes(specialization_types,
|
||||
parameter_types)});
|
||||
} else {
|
||||
result = Callable::cast(overloads[best]);
|
||||
}
|
||||
@ -1927,8 +1928,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 +1965,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());
|
||||
}
|
||||
@ -2542,10 +2544,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);
|
||||
|
@ -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,7 +53,8 @@ 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;
|
||||
}
|
||||
@ -112,7 +114,8 @@ class LocationReference {
|
||||
|
||||
const Type* ReferencedType() const {
|
||||
if (IsHeapReference()) {
|
||||
return ReferenceType::cast(heap_reference().type())->referenced_type();
|
||||
return *StructType::MatchUnaryGeneric(heap_reference().type(),
|
||||
TypeOracle::GetReferenceGeneric());
|
||||
}
|
||||
return GetVisitResult().type();
|
||||
}
|
||||
|
@ -297,6 +297,7 @@ void CreateFieldReferenceInstruction::TypeInstruction(
|
||||
stack->Push(TypeOracle::GetIntPtrType());
|
||||
}
|
||||
|
||||
// TODO(gsps): Remove in favor of a method on Reference<T>
|
||||
void LoadReferenceInstruction::TypeInstruction(Stack<const Type*>* stack,
|
||||
ControlFlowGraph* cfg) const {
|
||||
ExpectType(TypeOracle::GetIntPtrType(), stack->Pop());
|
||||
@ -305,6 +306,7 @@ void LoadReferenceInstruction::TypeInstruction(Stack<const Type*>* stack,
|
||||
stack->Push(type);
|
||||
}
|
||||
|
||||
// TODO(gsps): Remove in favor of a method on Reference<T>
|
||||
void StoreReferenceInstruction::TypeInstruction(Stack<const Type*>* stack,
|
||||
ControlFlowGraph* cfg) const {
|
||||
ExpectSubtype(stack->Pop(), type);
|
||||
|
@ -879,7 +879,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};
|
||||
}
|
||||
|
||||
|
@ -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,39 @@ 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());
|
||||
// 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 = TypeVisitor::ComputeType(generic_struct->declaration(),
|
||||
{{generic_struct, arg_types}});
|
||||
specializations.Add(arg_types, struct_type);
|
||||
return struct_type;
|
||||
}
|
||||
}
|
||||
|
||||
} // namespace torque
|
||||
} // namespace internal
|
||||
} // namespace v8
|
||||
|
@ -30,8 +30,11 @@ class TypeOracle : public ContextualClass<TypeOracle> {
|
||||
return result;
|
||||
}
|
||||
|
||||
static StructType* GetStructType(const std::string& name) {
|
||||
StructType* result = new StructType(CurrentNamespace(), name);
|
||||
static StructType* GetStructType(
|
||||
const std::string& basename,
|
||||
StructType::MaybeSpecializationKey specialized_from) {
|
||||
StructType* result =
|
||||
new StructType(CurrentNamespace(), basename, specialized_from);
|
||||
Get().aggregate_types_.push_back(std::unique_ptr<StructType>(result));
|
||||
return result;
|
||||
}
|
||||
@ -60,8 +63,17 @@ 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 const StructType* GetReferenceType(const Type* referenced_type) {
|
||||
return GetGenericStructTypeInstance(GetReferenceGeneric(),
|
||||
{referenced_type});
|
||||
}
|
||||
|
||||
static const std::vector<const BuiltinPointerType*>&
|
||||
@ -245,7 +257,6 @@ 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_;
|
||||
|
@ -110,25 +110,12 @@ void DeclareMethods(AggregateType* container_type,
|
||||
}
|
||||
}
|
||||
|
||||
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();
|
||||
});
|
||||
}
|
||||
return StructType::ComputeName(decl->name->value, args);
|
||||
}
|
||||
} // namespace
|
||||
|
||||
const StructType* TypeVisitor::ComputeType(StructDeclaration* decl) {
|
||||
const StructType* TypeVisitor::ComputeType(
|
||||
StructDeclaration* decl,
|
||||
StructType::MaybeSpecializationKey specialized_from) {
|
||||
CurrentSourcePosition::Scope position_activator(decl->pos);
|
||||
StructType* struct_type = TypeOracle::GetStructType(ComputeStructName(decl));
|
||||
StructType* struct_type =
|
||||
TypeOracle::GetStructType(decl->name->value, specialized_from);
|
||||
size_t offset = 0;
|
||||
for (auto& field : decl->fields) {
|
||||
CurrentSourcePosition::Scope position_activator(
|
||||
@ -214,34 +201,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 +215,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;
|
||||
|
@ -31,10 +31,13 @@ class TypeVisitor {
|
||||
|
||||
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);
|
||||
};
|
||||
|
||||
|
@ -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 << basename_;
|
||||
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;
|
||||
@ -560,9 +598,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);
|
||||
}
|
||||
|
@ -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;
|
||||
|
||||
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 std::string& basename,
|
||||
MaybeSpecializationKey specialized_from = base::nullopt)
|
||||
: AggregateType(Kind::kStructType, nullptr, nspace,
|
||||
ComputeName(basename, specialized_from)),
|
||||
basename_(basename),
|
||||
specialized_from_(specialized_from) {}
|
||||
|
||||
void Finalize() const override {
|
||||
is_finalized_ = true;
|
||||
CheckForDuplicateFields();
|
||||
}
|
||||
|
||||
const std::string& GetStructName() const { return name(); }
|
||||
static std::string ComputeName(const std::string& basename,
|
||||
MaybeSpecializationKey specialized_from);
|
||||
|
||||
std::string basename_;
|
||||
MaybeSpecializationKey specialized_from_;
|
||||
};
|
||||
|
||||
class TypeAlias;
|
||||
|
@ -898,7 +898,8 @@ namespace test {
|
||||
const ref:&Smi = & array.a;
|
||||
* ref = 3 + * ref;
|
||||
-- * ref;
|
||||
Swap(& array.b, array.GetA());
|
||||
// TODO(gsps): Remove explicit type arg once inference works
|
||||
Swap<Smi>(& array.b, array.GetA());
|
||||
check(array.a == 2);
|
||||
check(array.b == 9);
|
||||
}
|
||||
@ -993,7 +994,7 @@ namespace test {
|
||||
const snd: T2;
|
||||
}
|
||||
|
||||
macro Swap<T1: type, T2: type>(tuple: TestTuple<T1, T2>):
|
||||
macro TupleSwap<T1: type, T2: type>(tuple: TestTuple<T1, T2>):
|
||||
TestTuple<T2, T1> {
|
||||
return TestTuple<T2, T1>{fst: tuple.snd, snd: tuple.fst};
|
||||
}
|
||||
@ -1001,7 +1002,7 @@ namespace test {
|
||||
@export
|
||||
macro TestGenericStruct2(): TestTuple<Smi, intptr> {
|
||||
const intptrAndSmi = TestTuple<intptr, Smi>{fst: 1, snd: 2};
|
||||
const smiAndIntptr = Swap<intptr, Smi>(intptrAndSmi);
|
||||
const smiAndIntptr = TupleSwap<intptr, Smi>(intptrAndSmi);
|
||||
check(intptrAndSmi.fst == smiAndIntptr.snd);
|
||||
check(intptrAndSmi.snd == smiAndIntptr.fst);
|
||||
return smiAndIntptr;
|
||||
|
@ -20,6 +20,13 @@ constexpr const char* kTestTorquePrelude = R"(
|
||||
type void;
|
||||
type never;
|
||||
|
||||
namespace torque_internal {
|
||||
struct Reference<T: type> {
|
||||
const object: HeapObject;
|
||||
const offset: intptr;
|
||||
}
|
||||
}
|
||||
|
||||
type Tagged generates 'TNode<Object>' constexpr 'ObjectPtr';
|
||||
type Smi extends Tagged generates 'TNode<Smi>' constexpr 'Smi';
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user