Commit d7e02ea4 authored by Tobias Tebbi's avatar Tobias Tebbi Committed by Commit Bot

[torque] add const references and disallow const class field writes

- Allow type expression for abstract type supertypes.
  For consistency, and ease of implementation, also allow this for enums.
- Allow subtyping of structs. This requires changing all places where we
  checked for struct types and instead check if we have a subtype of a
  struct type.
- This allows defining two subtypes of the Reference<T> struct for
  mutable and constant references. Mutable references are a subtype of
  constant references.
- &T desugars to MutableReference<T>
  const &T desugars to ConstReference<T>
- A const field of a class produces a constant reference.
  A const field of a mutable reference to a struct is const.
  A mutable field of a const reference to a struct is const.
- It is possible to assign a new struct value to a mutable reference to
  a struct, even if the struct contains const fields. This is analogous
  to allowing assignments of let-bound structs with constant fields.

Not in this CL:
- A notion of const slices.
- Applying const to appropriate class fields.

Bug: v8:7793
Change-Id: I6e7b09d44f54db25f8bf812be5f3b554b80414e0
Reviewed-on: https://chromium-review.googlesource.com/c/v8/v8/+/2096615Reviewed-by: 's avatarNico Hartmann <nicohartmann@chromium.org>
Commit-Queue: Tobias Tebbi <tebbi@chromium.org>
Cr-Commit-Position: refs/heads/master@{#66759}
parent 3e1b6b40
...@@ -17,13 +17,12 @@ namespace torque_internal { ...@@ -17,13 +17,12 @@ namespace torque_internal {
const offset: intptr; const offset: intptr;
unsafeMarker: Unsafe; unsafeMarker: Unsafe;
} }
type ConstReference<T: type> extends Reference<T>;
type MutableReference<T: type> extends ConstReference<T>;
macro UnsafeNewReference<T: type>(object: HeapObject, offset: intptr):&T { macro UnsafeNewReference<T: type>(object: HeapObject, offset: intptr):&T {
return Reference<T>{ return %RawDownCast<&T>(
object: object, Reference<T>{object: object, offset: offset, unsafeMarker: Unsafe {}});
offset: offset,
unsafeMarker: Unsafe {}
};
} }
struct Slice<T: type> { struct Slice<T: type> {
......
...@@ -629,6 +629,8 @@ struct BasicTypeExpression : TypeExpression { ...@@ -629,6 +629,8 @@ struct BasicTypeExpression : TypeExpression {
is_constexpr(IsConstexprName(name)), is_constexpr(IsConstexprName(name)),
name(std::move(name)), name(std::move(name)),
generic_arguments(std::move(generic_arguments)) {} generic_arguments(std::move(generic_arguments)) {}
BasicTypeExpression(SourcePosition pos, std::string name)
: BasicTypeExpression(pos, {}, std::move(name), {}) {}
std::vector<std::string> namespace_qualification; std::vector<std::string> namespace_qualification;
bool is_constexpr; bool is_constexpr;
std::string name; std::string name;
...@@ -838,7 +840,7 @@ struct InstanceTypeConstraints { ...@@ -838,7 +840,7 @@ struct InstanceTypeConstraints {
struct AbstractTypeDeclaration : TypeDeclaration { struct AbstractTypeDeclaration : TypeDeclaration {
DEFINE_AST_NODE_LEAF_BOILERPLATE(AbstractTypeDeclaration) DEFINE_AST_NODE_LEAF_BOILERPLATE(AbstractTypeDeclaration)
AbstractTypeDeclaration(SourcePosition pos, Identifier* name, bool transient, AbstractTypeDeclaration(SourcePosition pos, Identifier* name, bool transient,
base::Optional<Identifier*> extends, base::Optional<TypeExpression*> extends,
base::Optional<std::string> generates) base::Optional<std::string> generates)
: TypeDeclaration(kKind, pos, name), : TypeDeclaration(kKind, pos, name),
is_constexpr(IsConstexprName(name->value)), is_constexpr(IsConstexprName(name->value)),
...@@ -847,7 +849,7 @@ struct AbstractTypeDeclaration : TypeDeclaration { ...@@ -847,7 +849,7 @@ struct AbstractTypeDeclaration : TypeDeclaration {
generates(std::move(generates)) {} generates(std::move(generates)) {}
bool is_constexpr; bool is_constexpr;
bool transient; bool transient;
base::Optional<Identifier*> extends; base::Optional<TypeExpression*> extends;
base::Optional<std::string> generates; base::Optional<std::string> generates;
}; };
......
...@@ -44,8 +44,8 @@ class ValueTypeFieldIterator { ...@@ -44,8 +44,8 @@ class ValueTypeFieldIterator {
int shift_bits; int shift_bits;
}; };
const Result operator*() const { const Result operator*() const {
if (const StructType* struct_type = StructType::DynamicCast(type_)) { if (auto struct_type = type_->StructSupertype()) {
const auto& field = struct_type->fields()[index_]; const auto& field = (*struct_type)->fields()[index_];
return {field.name_and_type, field.pos, *field.offset, 0, 0}; return {field.name_and_type, field.pos, *field.offset, 0, 0};
} }
const Type* type = type_; const Type* type = type_;
...@@ -87,9 +87,9 @@ class ValueTypeFieldsRange { ...@@ -87,9 +87,9 @@ class ValueTypeFieldsRange {
ValueTypeFieldIterator begin() { return {type_, 0}; } ValueTypeFieldIterator begin() { return {type_, 0}; }
ValueTypeFieldIterator end() { ValueTypeFieldIterator end() {
size_t index = 0; size_t index = 0;
const StructType* struct_type = StructType::DynamicCast(type_); base::Optional<const StructType*> struct_type = type_->StructSupertype();
if (struct_type && struct_type != TypeOracle::GetFloat64OrHoleType()) { if (struct_type && *struct_type != TypeOracle::GetFloat64OrHoleType()) {
index = struct_type->fields().size(); index = (*struct_type)->fields().size();
} }
const Type* type = type_; const Type* type = type_;
if (const auto type_wrapped_in_smi = if (const auto type_wrapped_in_smi =
...@@ -142,7 +142,7 @@ class DebugFieldType { ...@@ -142,7 +142,7 @@ class DebugFieldType {
// object types that are not included in the compilation of the debug helper // object types that are not included in the compilation of the debug helper
// library. // library.
std::string GetOriginalType(TypeStorage storage) const { std::string GetOriginalType(TypeStorage storage) const {
if (name_and_type_.type->IsStructType()) { if (name_and_type_.type->StructSupertype()) {
// There's no meaningful type we could use here, because the V8 symbols // There's no meaningful type we could use here, because the V8 symbols
// don't have any definition of a C++ struct matching this struct type. // don't have any definition of a C++ struct matching this struct type.
return ""; return "";
...@@ -259,7 +259,7 @@ void GenerateFieldValueAccessor(const Field& field, ...@@ -259,7 +259,7 @@ void GenerateFieldValueAccessor(const Field& field,
std::ostream& h_contents, std::ostream& h_contents,
std::ostream& cc_contents) { std::ostream& cc_contents) {
// Currently not implemented for struct fields. // Currently not implemented for struct fields.
if (field.name_and_type.type->IsStructType()) return; if (field.name_and_type.type->StructSupertype()) return;
DebugFieldType debug_field_type(field); DebugFieldType debug_field_type(field);
...@@ -274,25 +274,23 @@ void GenerateFieldValueAccessor(const Field& field, ...@@ -274,25 +274,23 @@ void GenerateFieldValueAccessor(const Field& field,
index_offset = " + offset * sizeof(value)"; index_offset = " + offset * sizeof(value)";
} }
if (!field.name_and_type.type->IsStructType()) { std::string field_value_type = debug_field_type.GetValueType(kUncompressed);
std::string field_value_type = debug_field_type.GetValueType(kUncompressed); h_contents << " Value<" << field_value_type << "> " << field_getter
h_contents << " Value<" << field_value_type << "> " << field_getter << "(d::MemoryAccessor accessor " << index_param << ") const;\n";
<< "(d::MemoryAccessor accessor " << index_param << ") const;\n"; cc_contents << "\nValue<" << field_value_type << "> Tq" << class_name
cc_contents << "\nValue<" << field_value_type << "> Tq" << class_name << "::" << field_getter << "(d::MemoryAccessor accessor"
<< "::" << field_getter << "(d::MemoryAccessor accessor" << index_param << ") const {\n";
<< index_param << ") const {\n"; cc_contents << " " << debug_field_type.GetValueType(kAsStoredInHeap)
cc_contents << " " << debug_field_type.GetValueType(kAsStoredInHeap) << " value{};\n";
<< " value{};\n"; cc_contents << " d::MemoryAccessResult validity = accessor("
cc_contents << " d::MemoryAccessResult validity = accessor(" << address_getter << "()" << index_offset
<< address_getter << "()" << index_offset << ", reinterpret_cast<uint8_t*>(&value), sizeof(value));\n";
<< ", reinterpret_cast<uint8_t*>(&value), sizeof(value));\n"; cc_contents << " return {validity, "
cc_contents << " return {validity, " << (debug_field_type.IsTagged()
<< (debug_field_type.IsTagged() ? "EnsureDecompressed(value, address_)"
? "EnsureDecompressed(value, address_)" : "value")
: "value") << "};\n";
<< "};\n"; cc_contents << "}\n";
cc_contents << "}\n";
}
} }
// Emits a portion of the member function GetProperties that is responsible for // Emits a portion of the member function GetProperties that is responsible for
......
...@@ -63,7 +63,8 @@ static const char* const CONST_INT31_TYPE_STRING = "constexpr int31"; ...@@ -63,7 +63,8 @@ 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_INT32_TYPE_STRING = "constexpr int32";
static const char* const CONST_FLOAT64_TYPE_STRING = "constexpr float64"; static const char* const CONST_FLOAT64_TYPE_STRING = "constexpr float64";
static const char* const TORQUE_INTERNAL_NAMESPACE_STRING = "torque_internal"; static const char* const TORQUE_INTERNAL_NAMESPACE_STRING = "torque_internal";
static const char* const REFERENCE_TYPE_STRING = "Reference"; static const char* const MUTABLE_REFERENCE_TYPE_STRING = "MutableReference";
static const char* const CONST_REFERENCE_TYPE_STRING = "ConstReference";
static const char* const SLICE_TYPE_STRING = "Slice"; static const char* const SLICE_TYPE_STRING = "Slice";
static const char* const WEAK_TYPE_STRING = "Weak"; static const char* const WEAK_TYPE_STRING = "Weak";
static const char* const SMI_TAGGED_TYPE_STRING = "SmiTagged"; static const char* const SMI_TAGGED_TYPE_STRING = "SmiTagged";
......
...@@ -6,6 +6,7 @@ ...@@ -6,6 +6,7 @@
#include "src/common/globals.h" #include "src/common/globals.h"
#include "src/torque/type-oracle.h" #include "src/torque/type-oracle.h"
#include "src/torque/types.h"
#include "src/torque/utils.h" #include "src/torque/utils.h"
namespace v8 { namespace v8 {
...@@ -181,7 +182,7 @@ void CSAGenerator::EmitInstruction( ...@@ -181,7 +182,7 @@ void CSAGenerator::EmitInstruction(
} }
out() << " "; out() << " ";
if (type->IsStructType()) { if (type->StructSupertype()) {
out() << "std::tie("; out() << "std::tie(";
PrintCommaSeparatedList(out(), results); PrintCommaSeparatedList(out(), results);
out() << ") = "; out() << ") = ";
...@@ -189,7 +190,7 @@ void CSAGenerator::EmitInstruction( ...@@ -189,7 +190,7 @@ void CSAGenerator::EmitInstruction(
out() << results[0] << " = "; out() << results[0] << " = ";
} }
out() << instruction.constant->external_name() << "(state_)"; out() << instruction.constant->external_name() << "(state_)";
if (type->IsStructType()) { if (type->StructSupertype()) {
out() << ".Flatten();\n"; out() << ".Flatten();\n";
} else { } else {
out() << ";\n"; out() << ";\n";
...@@ -239,7 +240,7 @@ void CSAGenerator::EmitInstruction(const CallIntrinsicInstruction& instruction, ...@@ -239,7 +240,7 @@ void CSAGenerator::EmitInstruction(const CallIntrinsicInstruction& instruction,
} }
out() << " "; out() << " ";
if (return_type->IsStructType()) { if (return_type->StructSupertype()) {
out() << "std::tie("; out() << "std::tie(";
PrintCommaSeparatedList(out(), results); PrintCommaSeparatedList(out(), results);
out() << ") = "; out() << ") = ";
...@@ -262,8 +263,9 @@ void CSAGenerator::EmitInstruction(const CallIntrinsicInstruction& instruction, ...@@ -262,8 +263,9 @@ void CSAGenerator::EmitInstruction(const CallIntrinsicInstruction& instruction,
ReportError("%RawDownCast error: ", *return_type, " is not a subtype of ", ReportError("%RawDownCast error: ", *return_type, " is not a subtype of ",
*original_type); *original_type);
} }
if (return_type->GetGeneratedTNodeTypeName() != if (!original_type->StructSupertype() &&
original_type->GetGeneratedTNodeTypeName()) { return_type->GetGeneratedTNodeTypeName() !=
original_type->GetGeneratedTNodeTypeName()) {
if (return_type->IsSubtypeOf(TypeOracle::GetTaggedType())) { if (return_type->IsSubtypeOf(TypeOracle::GetTaggedType())) {
out() << "TORQUE_CAST"; out() << "TORQUE_CAST";
} else { } else {
...@@ -318,7 +320,7 @@ void CSAGenerator::EmitInstruction(const CallIntrinsicInstruction& instruction, ...@@ -318,7 +320,7 @@ void CSAGenerator::EmitInstruction(const CallIntrinsicInstruction& instruction,
if (instruction.intrinsic->ExternalName() == "%FromConstexpr") { if (instruction.intrinsic->ExternalName() == "%FromConstexpr") {
out() << ")"; out() << ")";
} }
if (return_type->IsStructType()) { if (return_type->StructSupertype()) {
out() << ").Flatten();\n"; out() << ").Flatten();\n";
} else { } else {
out() << ");\n"; out() << ");\n";
...@@ -349,7 +351,7 @@ void CSAGenerator::EmitInstruction(const CallCsaMacroInstruction& instruction, ...@@ -349,7 +351,7 @@ void CSAGenerator::EmitInstruction(const CallCsaMacroInstruction& instruction,
std::string catch_name = std::string catch_name =
PreCallableExceptionPreparation(instruction.catch_block); PreCallableExceptionPreparation(instruction.catch_block);
out() << " "; out() << " ";
bool needs_flattening = return_type->IsStructType(); bool needs_flattening = return_type->StructSupertype().has_value();
if (needs_flattening) { if (needs_flattening) {
out() << "std::tie("; out() << "std::tie(";
PrintCommaSeparatedList(out(), results); PrintCommaSeparatedList(out(), results);
...@@ -448,7 +450,7 @@ void CSAGenerator::EmitInstruction( ...@@ -448,7 +450,7 @@ void CSAGenerator::EmitInstruction(
out() << ", &" << var_names[i][j]; out() << ", &" << var_names[i][j];
} }
} }
if (return_type->IsStructType()) { if (return_type->StructSupertype()) {
out() << ").Flatten();\n"; out() << ").Flatten();\n";
} else { } else {
out() << ");\n"; out() << ");\n";
...@@ -931,10 +933,10 @@ void CSAGenerator::EmitCSAValue(VisitResult result, ...@@ -931,10 +933,10 @@ void CSAGenerator::EmitCSAValue(VisitResult result,
std::ostream& out) { std::ostream& out) {
if (!result.IsOnStack()) { if (!result.IsOnStack()) {
out << result.constexpr_value(); out << result.constexpr_value();
} else if (auto* struct_type = StructType::DynamicCast(result.type())) { } else if (auto struct_type = result.type()->StructSupertype()) {
out << struct_type->GetGeneratedTypeName() << "{"; out << (*struct_type)->GetGeneratedTypeName() << "{";
bool first = true; bool first = true;
for (auto& field : struct_type->fields()) { for (auto& field : (*struct_type)->fields()) {
if (!first) { if (!first) {
out << ", "; out << ", ";
} }
......
...@@ -340,7 +340,7 @@ class Macro : public Callable { ...@@ -340,7 +340,7 @@ class Macro : public Callable {
bool ShouldBeInlined() const override { bool ShouldBeInlined() const override {
for (const LabelDeclaration& label : signature().labels) { for (const LabelDeclaration& label : signature().labels) {
for (const Type* type : label.types) { for (const Type* type : label.types) {
if (type->IsStructType()) return true; if (type->StructSupertype()) return true;
} }
} }
// Intrinsics that are used internally in Torque and implemented as torque // Intrinsics that are used internally in Torque and implemented as torque
......
...@@ -91,18 +91,16 @@ Builtin* DeclarationVisitor::CreateBuiltin(BuiltinDeclaration* decl, ...@@ -91,18 +91,16 @@ Builtin* DeclarationVisitor::CreateBuiltin(BuiltinDeclaration* decl,
} }
for (size_t i = 0; i < signature.types().size(); ++i) { for (size_t i = 0; i < signature.types().size(); ++i) {
if (const StructType* type = if (signature.types()[i]->StructSupertype()) {
StructType::DynamicCast(signature.types()[i])) { Error("Builtin do not support structs as arguments, but argument ",
Error("Builtin '", decl->name, "' uses the struct '", type->name(), signature.parameter_names[i], " has type ", *signature.types()[i],
"' as argument '", signature.parameter_names[i], ".");
"', which is not supported.");
} }
} }
if (const StructType* struct_type = if (signature.return_type->StructSupertype()) {
StructType::DynamicCast(signature.return_type)) { Error("Builtins cannot return structs, but the return type is ",
Error("Builtins ", decl->name, " cannot return structs ", *signature.return_type, ".");
struct_type->name());
} }
return Declarations::CreateBuiltin(std::move(external_name), return Declarations::CreateBuiltin(std::move(external_name),
......
This diff is collapsed.
...@@ -55,8 +55,7 @@ class LocationReference { ...@@ -55,8 +55,7 @@ class LocationReference {
// pointer. // pointer.
static LocationReference HeapReference(VisitResult heap_reference) { static LocationReference HeapReference(VisitResult heap_reference) {
LocationReference result; LocationReference result;
DCHECK(Type::MatchUnaryGeneric(heap_reference.type(), DCHECK(TypeOracle::MatchReferenceGeneric(heap_reference.type()));
TypeOracle::GetReferenceGeneric()));
result.heap_reference_ = std::move(heap_reference); result.heap_reference_ = std::move(heap_reference);
return result; return result;
} }
...@@ -92,7 +91,17 @@ class LocationReference { ...@@ -92,7 +91,17 @@ class LocationReference {
return result; return result;
} }
bool IsConst() const { return temporary_.has_value(); } bool IsConst() const {
if (IsHeapReference()) {
bool is_const;
bool success =
TypeOracle::MatchReferenceGeneric(heap_reference().type(), &is_const)
.has_value();
CHECK(success);
return is_const;
}
return IsTemporary();
}
bool IsVariableAccess() const { return variable_.has_value(); } bool IsVariableAccess() const { return variable_.has_value(); }
const VisitResult& variable() const { const VisitResult& variable() const {
...@@ -130,8 +139,7 @@ class LocationReference { ...@@ -130,8 +139,7 @@ class LocationReference {
const Type* ReferencedType() const { const Type* ReferencedType() const {
if (IsHeapReference()) { if (IsHeapReference()) {
return *Type::MatchUnaryGeneric(heap_reference().type(), return *TypeOracle::MatchReferenceGeneric(heap_reference().type());
TypeOracle::GetReferenceGeneric());
} }
if (IsHeapSlice()) { if (IsHeapSlice()) {
return *Type::MatchUnaryGeneric(heap_slice().type(), return *Type::MatchUnaryGeneric(heap_slice().type(),
...@@ -360,7 +368,7 @@ inline bool Binding<LocalValue>::CheckWritten() const { ...@@ -360,7 +368,7 @@ inline bool Binding<LocalValue>::CheckWritten() const {
auto binding = *manager_->current_bindings_[name_]; auto binding = *manager_->current_bindings_[name_];
const LocationReference& ref = binding->value; const LocationReference& ref = binding->value;
if (!ref.IsVariableAccess()) return false; if (!ref.IsVariableAccess()) return false;
return !ref.GetVisitResult().type()->IsStructType(); return !ref.GetVisitResult().type()->StructSupertype();
} }
template <> template <>
inline std::string Binding<LocalLabel>::BindingTypeString() const { inline std::string Binding<LocalLabel>::BindingTypeString() const {
...@@ -411,7 +419,7 @@ class ImplementationVisitor { ...@@ -411,7 +419,7 @@ class ImplementationVisitor {
LocationReference GenerateFieldReference(VisitResult object, LocationReference GenerateFieldReference(VisitResult object,
const Field& field, const Field& field,
const ClassType* class_type); const ClassType* class_type);
LocationReference GenerateFieldReference( LocationReference GenerateFieldReferenceForInit(
VisitResult object, const Field& field, VisitResult object, const Field& field,
const LayoutForInitialization& layout); const LayoutForInitialization& layout);
VisitResult GenerateArrayLength( VisitResult GenerateArrayLength(
...@@ -437,6 +445,7 @@ class ImplementationVisitor { ...@@ -437,6 +445,7 @@ class ImplementationVisitor {
LocationReference GetLocationReference(FieldAccessExpression* expr); LocationReference GetLocationReference(FieldAccessExpression* expr);
LocationReference GenerateFieldAccess( LocationReference GenerateFieldAccess(
LocationReference reference, const std::string& fieldname, LocationReference reference, const std::string& fieldname,
bool ignore_stuct_field_constness = false,
base::Optional<SourcePosition> pos = {}); base::Optional<SourcePosition> pos = {});
LocationReference GetLocationReference(ElementAccessExpression* expr); LocationReference GetLocationReference(ElementAccessExpression* expr);
......
...@@ -9,6 +9,7 @@ ...@@ -9,6 +9,7 @@
#include <unordered_map> #include <unordered_map>
#include "src/flags/flags.h" #include "src/flags/flags.h"
#include "src/torque/ast.h"
#include "src/torque/constants.h" #include "src/torque/constants.h"
#include "src/torque/declarations.h" #include "src/torque/declarations.h"
#include "src/torque/earley-parser.h" #include "src/torque/earley-parser.h"
...@@ -302,6 +303,14 @@ void CheckNotDeferredStatement(Statement* statement) { ...@@ -302,6 +303,14 @@ void CheckNotDeferredStatement(Statement* statement) {
} }
} }
TypeExpression* AddConstexpr(TypeExpression* type) {
BasicTypeExpression* basic = BasicTypeExpression::DynamicCast(type);
if (!basic) Error("Unsupported extends clause.").Throw();
return MakeNode<BasicTypeExpression>(basic->namespace_qualification,
CONSTEXPR_TYPE_PREFIX + basic->name,
basic->generic_arguments);
}
Expression* MakeCall(IdentifierExpression* callee, Expression* MakeCall(IdentifierExpression* callee,
base::Optional<Expression*> target, base::Optional<Expression*> target,
std::vector<Expression*> arguments, std::vector<Expression*> arguments,
...@@ -661,7 +670,7 @@ base::Optional<ParseResult> MakeAbstractTypeDeclaration( ...@@ -661,7 +670,7 @@ base::Optional<ParseResult> MakeAbstractTypeDeclaration(
NamingConventionError("Type", name, "UpperCamelCase"); NamingConventionError("Type", name, "UpperCamelCase");
} }
auto generic_parameters = child_results->NextAs<GenericParameters>(); auto generic_parameters = child_results->NextAs<GenericParameters>();
auto extends = child_results->NextAs<base::Optional<Identifier*>>(); auto extends = child_results->NextAs<base::Optional<TypeExpression*>>();
auto generates = child_results->NextAs<base::Optional<std::string>>(); auto generates = child_results->NextAs<base::Optional<std::string>>();
TypeDeclaration* type_decl = MakeNode<AbstractTypeDeclaration>( TypeDeclaration* type_decl = MakeNode<AbstractTypeDeclaration>(
name, transient, extends, std::move(generates)); name, transient, extends, std::move(generates));
...@@ -680,11 +689,9 @@ base::Optional<ParseResult> MakeAbstractTypeDeclaration( ...@@ -680,11 +689,9 @@ base::Optional<ParseResult> MakeAbstractTypeDeclaration(
MakeNode<Identifier>(CONSTEXPR_TYPE_PREFIX + name->value); MakeNode<Identifier>(CONSTEXPR_TYPE_PREFIX + name->value);
constexpr_name->pos = name->pos; constexpr_name->pos = name->pos;
base::Optional<Identifier*> constexpr_extends; base::Optional<TypeExpression*> constexpr_extends;
if (extends) { if (extends) {
constexpr_extends = constexpr_extends = AddConstexpr(*extends);
MakeNode<Identifier>(CONSTEXPR_TYPE_PREFIX + (*extends)->value);
(*constexpr_extends)->pos = name->pos;
} }
TypeDeclaration* constexpr_decl = MakeNode<AbstractTypeDeclaration>( TypeDeclaration* constexpr_decl = MakeNode<AbstractTypeDeclaration>(
constexpr_name, transient, constexpr_extends, constexpr_generates); constexpr_name, transient, constexpr_extends, constexpr_generates);
...@@ -1090,12 +1097,15 @@ base::Optional<ParseResult> MakeFunctionTypeExpression( ...@@ -1090,12 +1097,15 @@ base::Optional<ParseResult> MakeFunctionTypeExpression(
base::Optional<ParseResult> MakeReferenceTypeExpression( base::Optional<ParseResult> MakeReferenceTypeExpression(
ParseResultIterator* child_results) { ParseResultIterator* child_results) {
auto is_const = child_results->NextAs<bool>();
auto referenced_type = child_results->NextAs<TypeExpression*>(); auto referenced_type = child_results->NextAs<TypeExpression*>();
std::vector<std::string> namespace_qualification{ std::vector<std::string> namespace_qualification{
TORQUE_INTERNAL_NAMESPACE_STRING}; TORQUE_INTERNAL_NAMESPACE_STRING};
std::vector<TypeExpression*> generic_arguments{referenced_type}; std::vector<TypeExpression*> generic_arguments{referenced_type};
TypeExpression* result = MakeNode<BasicTypeExpression>( TypeExpression* result = MakeNode<BasicTypeExpression>(
namespace_qualification, REFERENCE_TYPE_STRING, generic_arguments); namespace_qualification,
is_const ? CONST_REFERENCE_TYPE_STRING : MUTABLE_REFERENCE_TYPE_STRING,
generic_arguments);
return ParseResult{result}; return ParseResult{result};
} }
...@@ -1149,7 +1159,8 @@ base::Optional<ParseResult> MakeEnumDeclaration( ...@@ -1149,7 +1159,8 @@ base::Optional<ParseResult> MakeEnumDeclaration(
const bool is_extern = child_results->NextAs<bool>(); const bool is_extern = child_results->NextAs<bool>();
auto name_identifier = child_results->NextAs<Identifier*>(); auto name_identifier = child_results->NextAs<Identifier*>();
auto name = name_identifier->value; auto name = name_identifier->value;
auto base_identifier = child_results->NextAs<base::Optional<Identifier*>>(); auto base_type_expression =
child_results->NextAs<base::Optional<TypeExpression*>>();
auto constexpr_generates_opt = auto constexpr_generates_opt =
child_results->NextAs<base::Optional<std::string>>(); child_results->NextAs<base::Optional<std::string>>();
auto entries = child_results->NextAs<std::vector<Identifier*>>(); auto entries = child_results->NextAs<std::vector<Identifier*>>();
...@@ -1167,12 +1178,12 @@ base::Optional<ParseResult> MakeEnumDeclaration( ...@@ -1167,12 +1178,12 @@ base::Optional<ParseResult> MakeEnumDeclaration(
auto constexpr_generates = auto constexpr_generates =
constexpr_generates_opt ? *constexpr_generates_opt : name; constexpr_generates_opt ? *constexpr_generates_opt : name;
const bool generate_nonconstexpr = base_identifier.has_value(); const bool generate_nonconstexpr = base_type_expression.has_value();
std::vector<Declaration*> result; std::vector<Declaration*> result;
// Build non-constexpr types. // Build non-constexpr types.
if (generate_nonconstexpr) { if (generate_nonconstexpr) {
DCHECK(base_identifier.has_value()); DCHECK(base_type_expression.has_value());
if (is_open) { if (is_open) {
// For open enumerations, we define an abstract type and inherit all // For open enumerations, we define an abstract type and inherit all
...@@ -1184,12 +1195,16 @@ base::Optional<ParseResult> MakeEnumDeclaration( ...@@ -1184,12 +1195,16 @@ base::Optional<ParseResult> MakeEnumDeclaration(
// type kEntryN extends Enum; // type kEntryN extends Enum;
// } // }
auto type_decl = MakeNode<AbstractTypeDeclaration>( auto type_decl = MakeNode<AbstractTypeDeclaration>(
name_identifier, false, base_identifier, base::nullopt); name_identifier, false, base_type_expression, base::nullopt);
TypeExpression* name_type_expression =
MakeNode<BasicTypeExpression>(name_identifier->value);
name_type_expression->pos = name_identifier->pos;
std::vector<Declaration*> entry_decls; std::vector<Declaration*> entry_decls;
for (const auto& entry_name_identifier : entries) { for (const auto& entry_name_identifier : entries) {
entry_decls.push_back(MakeNode<AbstractTypeDeclaration>( entry_decls.push_back(MakeNode<AbstractTypeDeclaration>(
entry_name_identifier, false, name_identifier, base::nullopt)); entry_name_identifier, false, name_type_expression, base::nullopt));
} }
result.push_back(type_decl); result.push_back(type_decl);
...@@ -1208,7 +1223,7 @@ base::Optional<ParseResult> MakeEnumDeclaration( ...@@ -1208,7 +1223,7 @@ base::Optional<ParseResult> MakeEnumDeclaration(
std::vector<Declaration*> entry_decls; std::vector<Declaration*> entry_decls;
for (const auto& entry_name_identifier : entries) { for (const auto& entry_name_identifier : entries) {
entry_decls.push_back(MakeNode<AbstractTypeDeclaration>( entry_decls.push_back(MakeNode<AbstractTypeDeclaration>(
entry_name_identifier, false, base_identifier, base::nullopt)); entry_name_identifier, false, base_type_expression, base::nullopt));
auto entry_type = MakeNode<BasicTypeExpression>( auto entry_type = MakeNode<BasicTypeExpression>(
std::vector<std::string>{name}, entry_name_identifier->value, std::vector<std::string>{name}, entry_name_identifier->value,
...@@ -1238,13 +1253,15 @@ base::Optional<ParseResult> MakeEnumDeclaration( ...@@ -1238,13 +1253,15 @@ base::Optional<ParseResult> MakeEnumDeclaration(
// } // }
Identifier* constexpr_type_identifier = Identifier* constexpr_type_identifier =
MakeNode<Identifier>(std::string(CONSTEXPR_TYPE_PREFIX) + name); MakeNode<Identifier>(std::string(CONSTEXPR_TYPE_PREFIX) + name);
base::Optional<Identifier*> base_constexpr_type_identifier = base::nullopt; TypeExpression* constexpr_type_expression = MakeNode<BasicTypeExpression>(
if (base_identifier) { std::string(CONSTEXPR_TYPE_PREFIX) + name);
base_constexpr_type_identifier = MakeNode<Identifier>( base::Optional<TypeExpression*> base_constexpr_type_expression =
std::string(CONSTEXPR_TYPE_PREFIX) + (*base_identifier)->value); base::nullopt;
if (base_type_expression) {
base_constexpr_type_expression = AddConstexpr(*base_type_expression);
} }
result.push_back(MakeNode<AbstractTypeDeclaration>( result.push_back(MakeNode<AbstractTypeDeclaration>(
constexpr_type_identifier, false, base_constexpr_type_identifier, constexpr_type_identifier, false, base_constexpr_type_expression,
constexpr_generates)); constexpr_generates));
TypeExpression* type_expr = nullptr; TypeExpression* type_expr = nullptr;
...@@ -1252,10 +1269,7 @@ base::Optional<ParseResult> MakeEnumDeclaration( ...@@ -1252,10 +1269,7 @@ base::Optional<ParseResult> MakeEnumDeclaration(
Identifier* fromconstexpr_parameter_identifier = nullptr; Identifier* fromconstexpr_parameter_identifier = nullptr;
Statement* fromconstexpr_body = nullptr; Statement* fromconstexpr_body = nullptr;
if (generate_nonconstexpr) { if (generate_nonconstexpr) {
DCHECK(base_identifier.has_value()); DCHECK(base_type_expression.has_value());
TypeExpression* base_type_expr = MakeNode<BasicTypeExpression>(
std::vector<std::string>{}, (*base_identifier)->value,
std::vector<TypeExpression*>{});
type_expr = MakeNode<BasicTypeExpression>( type_expr = MakeNode<BasicTypeExpression>(
std::vector<std::string>{}, name, std::vector<TypeExpression*>{}); std::vector<std::string>{}, name, std::vector<TypeExpression*>{});
...@@ -1268,7 +1282,7 @@ base::Optional<ParseResult> MakeEnumDeclaration( ...@@ -1268,7 +1282,7 @@ base::Optional<ParseResult> MakeEnumDeclaration(
std::vector<TypeExpression*>{type_expr}, std::vector<TypeExpression*>{type_expr},
std::vector<Expression*>{MakeNode<IntrinsicCallExpression>( std::vector<Expression*>{MakeNode<IntrinsicCallExpression>(
MakeNode<Identifier>("%FromConstexpr"), MakeNode<Identifier>("%FromConstexpr"),
std::vector<TypeExpression*>{base_type_expr}, std::vector<TypeExpression*>{*base_type_expression},
std::vector<Expression*>{MakeNode<IdentifierExpression>( std::vector<Expression*>{MakeNode<IdentifierExpression>(
std::vector<std::string>{}, std::vector<std::string>{},
fromconstexpr_parameter_identifier)})})); fromconstexpr_parameter_identifier)})}));
...@@ -1286,7 +1300,7 @@ base::Optional<ParseResult> MakeEnumDeclaration( ...@@ -1286,7 +1300,7 @@ base::Optional<ParseResult> MakeEnumDeclaration(
entry_decls.push_back(MakeNode<AbstractTypeDeclaration>( entry_decls.push_back(MakeNode<AbstractTypeDeclaration>(
MakeNode<Identifier>(entry_constexpr_type), false, MakeNode<Identifier>(entry_constexpr_type), false,
constexpr_type_identifier, constexpr_generates)); constexpr_type_expression, constexpr_generates));
// namespace Enum { // namespace Enum {
// const kEntry0: constexpr kEntry0 constexpr 'Enum::kEntry0'; // const kEntry0: constexpr kEntry0 constexpr 'Enum::kEntry0';
...@@ -1972,7 +1986,8 @@ struct TorqueGrammar : Grammar { ...@@ -1972,7 +1986,8 @@ struct TorqueGrammar : Grammar {
Rule({Token("builtin"), Token("("), typeList, Token(")"), Token("=>"), Rule({Token("builtin"), Token("("), typeList, Token(")"), Token("=>"),
&simpleType}, &simpleType},
MakeFunctionTypeExpression), MakeFunctionTypeExpression),
Rule({Token("&"), &simpleType}, MakeReferenceTypeExpression)}; Rule({CheckIf(Token("const")), Token("&"), &simpleType},
MakeReferenceTypeExpression)};
// Result: TypeExpression* // Result: TypeExpression*
Symbol type = {Rule({&simpleType}), Rule({&type, Token("|"), &simpleType}, Symbol type = {Rule({&simpleType}), Rule({&type, Token("|"), &simpleType},
...@@ -2356,7 +2371,7 @@ struct TorqueGrammar : Grammar { ...@@ -2356,7 +2371,7 @@ struct TorqueGrammar : Grammar {
AsSingletonVector<Declaration*, MakeBitFieldStructDeclaration>()), AsSingletonVector<Declaration*, MakeBitFieldStructDeclaration>()),
Rule({CheckIf(Token("transient")), Token("type"), &name, Rule({CheckIf(Token("transient")), Token("type"), &name,
TryOrDefault<GenericParameters>(&genericParameters), TryOrDefault<GenericParameters>(&genericParameters),
Optional<Identifier*>(Sequence({Token("extends"), &name})), Optional<TypeExpression*>(Sequence({Token("extends"), &type})),
Optional<std::string>( Optional<std::string>(
Sequence({Token("generates"), &externalString})), Sequence({Token("generates"), &externalString})),
Optional<std::string>( Optional<std::string>(
...@@ -2406,7 +2421,7 @@ struct TorqueGrammar : Grammar { ...@@ -2406,7 +2421,7 @@ struct TorqueGrammar : Grammar {
Rule({Token("#include"), &externalString}, Rule({Token("#include"), &externalString},
AsSingletonVector<Declaration*, MakeCppIncludeDeclaration>()), AsSingletonVector<Declaration*, MakeCppIncludeDeclaration>()),
Rule({CheckIf(Token("extern")), Token("enum"), &name, Rule({CheckIf(Token("extern")), Token("enum"), &name,
Optional<Identifier*>(Sequence({Token("extends"), &name})), Optional<TypeExpression*>(Sequence({Token("extends"), &type})),
Optional<std::string>( Optional<std::string>(
Sequence({Token("constexpr"), &externalString})), Sequence({Token("constexpr"), &externalString})),
Token("{"), NonemptyList<Identifier*>(&name, Token(",")), Token("{"), NonemptyList<Identifier*>(&name, Token(",")),
......
...@@ -3,6 +3,7 @@ ...@@ -3,6 +3,7 @@
// found in the LICENSE file. // found in the LICENSE file.
#include "src/torque/type-oracle.h" #include "src/torque/type-oracle.h"
#include "src/base/optional.h"
#include "src/torque/type-visitor.h" #include "src/torque/type-visitor.h"
#include "src/torque/types.h" #include "src/torque/types.h"
...@@ -80,6 +81,21 @@ std::vector<const ClassType*> TypeOracle::GetClasses() { ...@@ -80,6 +81,21 @@ std::vector<const ClassType*> TypeOracle::GetClasses() {
return result; return result;
} }
base::Optional<const Type*> TypeOracle::MatchReferenceGeneric(
const Type* reference_type, bool* is_const) {
if (auto type = Type::MatchUnaryGeneric(reference_type,
GetMutableReferenceGeneric())) {
if (is_const) *is_const = false;
return type;
}
if (auto type =
Type::MatchUnaryGeneric(reference_type, GetConstReferenceGeneric())) {
if (is_const) *is_const = true;
return type;
}
return base::nullopt;
}
} // namespace torque } // namespace torque
} // namespace internal } // namespace internal
} // namespace v8 } // namespace v8
...@@ -81,11 +81,22 @@ class TypeOracle : public ContextualClass<TypeOracle> { ...@@ -81,11 +81,22 @@ class TypeOracle : public ContextualClass<TypeOracle> {
static const Type* GetGenericTypeInstance(GenericType* generic_type, static const Type* GetGenericTypeInstance(GenericType* generic_type,
TypeVector arg_types); TypeVector arg_types);
static GenericType* GetReferenceGeneric() { static GenericType* GetReferenceGeneric(bool is_const) {
return Declarations::LookupUniqueGenericType(QualifiedName( return Declarations::LookupUniqueGenericType(
{TORQUE_INTERNAL_NAMESPACE_STRING}, REFERENCE_TYPE_STRING)); QualifiedName({TORQUE_INTERNAL_NAMESPACE_STRING},
is_const ? CONST_REFERENCE_TYPE_STRING
: MUTABLE_REFERENCE_TYPE_STRING));
}
static GenericType* GetConstReferenceGeneric() {
return GetReferenceGeneric(true);
}
static GenericType* GetMutableReferenceGeneric() {
return GetReferenceGeneric(false);
} }
static base::Optional<const Type*> MatchReferenceGeneric(
const Type* reference_type, bool* is_const = nullptr);
static GenericType* GetSliceGeneric() { static GenericType* GetSliceGeneric() {
return Declarations::LookupUniqueGenericType( return Declarations::LookupUniqueGenericType(
QualifiedName({TORQUE_INTERNAL_NAMESPACE_STRING}, SLICE_TYPE_STRING)); QualifiedName({TORQUE_INTERNAL_NAMESPACE_STRING}, SLICE_TYPE_STRING));
...@@ -99,8 +110,16 @@ class TypeOracle : public ContextualClass<TypeOracle> { ...@@ -99,8 +110,16 @@ class TypeOracle : public ContextualClass<TypeOracle> {
return Declarations::LookupGlobalUniqueGenericType(SMI_TAGGED_TYPE_STRING); return Declarations::LookupGlobalUniqueGenericType(SMI_TAGGED_TYPE_STRING);
} }
static const Type* GetReferenceType(const Type* referenced_type) { static const Type* GetReferenceType(const Type* referenced_type,
return GetGenericTypeInstance(GetReferenceGeneric(), {referenced_type}); bool is_const) {
return GetGenericTypeInstance(GetReferenceGeneric(is_const),
{referenced_type});
}
static const Type* GetConstReferenceType(const Type* referenced_type) {
return GetReferenceType(referenced_type, true);
}
static const Type* GetMutableReferenceType(const Type* referenced_type) {
return GetReferenceType(referenced_type, false);
} }
static const Type* GetSliceType(const Type* referenced_type) { static const Type* GetSliceType(const Type* referenced_type) {
......
...@@ -81,7 +81,7 @@ const AbstractType* TypeVisitor::ComputeType( ...@@ -81,7 +81,7 @@ const AbstractType* TypeVisitor::ComputeType(
const Type* parent_type = nullptr; const Type* parent_type = nullptr;
if (decl->extends) { if (decl->extends) {
parent_type = Declarations::LookupType(*decl->extends); parent_type = TypeVisitor::ComputeType(*decl->extends);
if (parent_type->IsUnionType()) { if (parent_type->IsUnionType()) {
// UnionType::IsSupertypeOf requires that types can only extend from non- // UnionType::IsSupertypeOf requires that types can only extend from non-
// union types in order to work correctly. // union types in order to work correctly.
...@@ -90,10 +90,6 @@ const AbstractType* TypeVisitor::ComputeType( ...@@ -90,10 +90,6 @@ const AbstractType* TypeVisitor::ComputeType(
} }
} }
if (generates == "" && parent_type) {
generates = parent_type->GetGeneratedTNodeTypeName();
}
if (decl->is_constexpr && decl->transient) { if (decl->is_constexpr && decl->transient) {
ReportError("cannot declare a transient type that is also constexpr"); ReportError("cannot declare a transient type that is also constexpr");
} }
......
...@@ -113,6 +113,15 @@ base::Optional<const ClassType*> Type::ClassSupertype() const { ...@@ -113,6 +113,15 @@ base::Optional<const ClassType*> Type::ClassSupertype() const {
return base::nullopt; return base::nullopt;
} }
base::Optional<const StructType*> Type::StructSupertype() const {
for (const Type* t = this; t != nullptr; t = t->parent()) {
if (auto* struct_type = StructType::DynamicCast(t)) {
return struct_type;
}
}
return base::nullopt;
}
// static // static
const Type* Type::CommonSupertype(const Type* a, const Type* b) { const Type* Type::CommonSupertype(const Type* a, const Type* b) {
int diff = a->Depth() - b->Depth(); int diff = a->Depth() - b->Depth();
...@@ -161,6 +170,7 @@ std::string Type::GetGeneratedTNodeTypeName() const { ...@@ -161,6 +170,7 @@ std::string Type::GetGeneratedTNodeTypeName() const {
} }
std::string AbstractType::GetGeneratedTNodeTypeNameImpl() const { std::string AbstractType::GetGeneratedTNodeTypeNameImpl() const {
if (generated_type_.empty()) return parent()->GetGeneratedTNodeTypeName();
return generated_type_; return generated_type_;
} }
...@@ -391,9 +401,8 @@ StructType::Classification StructType::ClassifyContents() const { ...@@ -391,9 +401,8 @@ StructType::Classification StructType::ClassifyContents() const {
const Type* field_type = struct_field.name_and_type.type; const Type* field_type = struct_field.name_and_type.type;
if (field_type->IsSubtypeOf(TypeOracle::GetTaggedType())) { if (field_type->IsSubtypeOf(TypeOracle::GetTaggedType())) {
result |= ClassificationFlag::kTagged; result |= ClassificationFlag::kTagged;
} else if (const StructType* field_as_struct = } else if (auto field_as_struct = field_type->StructSupertype()) {
StructType::DynamicCast(field_type)) { result |= (*field_as_struct)->ClassifyContents();
result |= field_as_struct->ClassifyContents();
} else { } else {
result |= ClassificationFlag::kUntagged; result |= ClassificationFlag::kUntagged;
} }
...@@ -405,6 +414,12 @@ StructType::Classification StructType::ClassifyContents() const { ...@@ -405,6 +414,12 @@ StructType::Classification StructType::ClassifyContents() const {
std::string Type::ComputeName(const std::string& basename, std::string Type::ComputeName(const std::string& basename,
MaybeSpecializationKey specialized_from) { MaybeSpecializationKey specialized_from) {
if (!specialized_from) return basename; if (!specialized_from) return basename;
if (specialized_from->generic == TypeOracle::GetConstReferenceGeneric()) {
return torque::ToString("const &", *specialized_from->specialized_types[0]);
}
if (specialized_from->generic == TypeOracle::GetMutableReferenceGeneric()) {
return torque::ToString("&", *specialized_from->specialized_types[0]);
}
std::stringstream s; std::stringstream s;
s << basename << "<"; s << basename << "<";
bool first = true; bool first = true;
...@@ -572,33 +587,35 @@ void ClassType::GenerateAccessors() { ...@@ -572,33 +587,35 @@ void ClassType::GenerateAccessors() {
load_signature, load_body, base::nullopt); load_signature, load_body, base::nullopt);
// Store accessor // Store accessor
IdentifierExpression* value = MakeNode<IdentifierExpression>( if (!field.const_qualified) {
std::vector<std::string>{}, MakeNode<Identifier>(std::string{"v"})); IdentifierExpression* value = MakeNode<IdentifierExpression>(
std::string store_macro_name = "Store" + this->name() + camel_field_name; std::vector<std::string>{}, MakeNode<Identifier>(std::string{"v"}));
Signature store_signature; std::string store_macro_name = "Store" + this->name() + camel_field_name;
store_signature.parameter_names.push_back(MakeNode<Identifier>("o")); Signature store_signature;
store_signature.parameter_types.types.push_back(this); store_signature.parameter_names.push_back(MakeNode<Identifier>("o"));
if (field.index) { store_signature.parameter_types.types.push_back(this);
store_signature.parameter_names.push_back(MakeNode<Identifier>("i")); if (field.index) {
store_signature.parameter_types.types.push_back( store_signature.parameter_names.push_back(MakeNode<Identifier>("i"));
TypeOracle::GetIntPtrType()); store_signature.parameter_types.types.push_back(
} TypeOracle::GetIntPtrType());
store_signature.parameter_names.push_back(MakeNode<Identifier>("v")); }
store_signature.parameter_types.types.push_back(field.name_and_type.type); store_signature.parameter_names.push_back(MakeNode<Identifier>("v"));
store_signature.parameter_types.var_args = false; store_signature.parameter_types.types.push_back(field.name_and_type.type);
// TODO(danno): Store macros probably should return their value argument store_signature.parameter_types.var_args = false;
store_signature.return_type = TypeOracle::GetVoidType(); // TODO(danno): Store macros probably should return their value argument
Expression* store_expression = MakeNode<FieldAccessExpression>( store_signature.return_type = TypeOracle::GetVoidType();
parameter, MakeNode<Identifier>(field.name_and_type.name)); Expression* store_expression = MakeNode<FieldAccessExpression>(
if (field.index) { parameter, MakeNode<Identifier>(field.name_and_type.name));
store_expression = if (field.index) {
MakeNode<ElementAccessExpression>(store_expression, index); store_expression =
MakeNode<ElementAccessExpression>(store_expression, index);
}
Statement* store_body = MakeNode<ExpressionStatement>(
MakeNode<AssignmentExpression>(store_expression, value));
Declarations::DeclareMacro(store_macro_name, true, base::nullopt,
store_signature, store_body, base::nullopt,
false);
} }
Statement* store_body = MakeNode<ExpressionStatement>(
MakeNode<AssignmentExpression>(store_expression, value));
Declarations::DeclareMacro(store_macro_name, true, base::nullopt,
store_signature, store_body, base::nullopt,
false);
} }
} }
...@@ -715,7 +732,7 @@ VisitResult ProjectStructField(VisitResult structure, ...@@ -715,7 +732,7 @@ VisitResult ProjectStructField(VisitResult structure,
BottomOffset begin = structure.stack_range().begin(); BottomOffset begin = structure.stack_range().begin();
// Check constructor this super classes for fields. // Check constructor this super classes for fields.
const StructType* type = StructType::cast(structure.type()); const StructType* type = *structure.type()->StructSupertype();
auto& fields = type->fields(); auto& fields = type->fields();
for (auto& field : fields) { for (auto& field : fields) {
BottomOffset end = begin + LoweredSlotCount(field.name_and_type.type); BottomOffset end = begin + LoweredSlotCount(field.name_and_type.type);
...@@ -734,8 +751,8 @@ void AppendLoweredTypes(const Type* type, std::vector<const Type*>* result) { ...@@ -734,8 +751,8 @@ void AppendLoweredTypes(const Type* type, std::vector<const Type*>* result) {
DCHECK_NE(type, TypeOracle::GetNeverType()); DCHECK_NE(type, TypeOracle::GetNeverType());
if (type->IsConstexpr()) return; if (type->IsConstexpr()) return;
if (type == TypeOracle::GetVoidType()) return; if (type == TypeOracle::GetVoidType()) return;
if (auto* s = StructType::DynamicCast(type)) { if (base::Optional<const StructType*> s = type->StructSupertype()) {
for (const Field& field : s->fields()) { for (const Field& field : (*s)->fields()) {
AppendLoweredTypes(field.name_and_type.type, result); AppendLoweredTypes(field.name_and_type.type, result);
} }
} else { } else {
...@@ -838,9 +855,9 @@ size_t StructType::AlignmentLog2() const { ...@@ -838,9 +855,9 @@ size_t StructType::AlignmentLog2() const {
void Field::ValidateAlignment(ResidueClass at_offset) const { void Field::ValidateAlignment(ResidueClass at_offset) const {
const Type* type = name_and_type.type; const Type* type = name_and_type.type;
const StructType* struct_type = StructType::DynamicCast(type); base::Optional<const StructType*> struct_type = type->StructSupertype();
if (struct_type && struct_type != TypeOracle::GetFloat64OrHoleType()) { if (struct_type && struct_type != TypeOracle::GetFloat64OrHoleType()) {
for (const Field& field : struct_type->fields()) { for (const Field& field : (*struct_type)->fields()) {
field.ValidateAlignment(at_offset); field.ValidateAlignment(at_offset);
size_t field_size = std::get<0>(field.GetFieldSizeInformation()); size_t field_size = std::get<0>(field.GetFieldSizeInformation());
at_offset += field_size; at_offset += field_size;
...@@ -894,12 +911,12 @@ base::Optional<std::tuple<size_t, std::string>> SizeOf(const Type* type) { ...@@ -894,12 +911,12 @@ base::Optional<std::tuple<size_t, std::string>> SizeOf(const Type* type) {
} else if (type->IsSubtypeOf(TypeOracle::GetUIntPtrType())) { } else if (type->IsSubtypeOf(TypeOracle::GetUIntPtrType())) {
size = TargetArchitecture::RawPtrSize(); size = TargetArchitecture::RawPtrSize();
size_string = "kIntptrSize"; size_string = "kIntptrSize";
} else if (const StructType* struct_type = StructType::DynamicCast(type)) { } else if (auto struct_type = type->StructSupertype()) {
if (type == TypeOracle::GetFloat64OrHoleType()) { if (type == TypeOracle::GetFloat64OrHoleType()) {
size = kDoubleSize; size = kDoubleSize;
size_string = "kDoubleSize"; size_string = "kDoubleSize";
} else { } else {
size = struct_type->PackedSize(); size = (*struct_type)->PackedSize();
size_string = std::to_string(size); size_string = std::to_string(size);
} }
} else { } else {
......
...@@ -133,6 +133,7 @@ class V8_EXPORT_PRIVATE Type : public TypeBase { ...@@ -133,6 +133,7 @@ class V8_EXPORT_PRIVATE Type : public TypeBase {
virtual const Type* NonConstexprVersion() const { return this; } virtual const Type* NonConstexprVersion() const { return this; }
std::string GetConstexprGeneratedTypeName() const; std::string GetConstexprGeneratedTypeName() const;
base::Optional<const ClassType*> ClassSupertype() const; base::Optional<const ClassType*> ClassSupertype() const;
base::Optional<const StructType*> StructSupertype() const;
virtual std::vector<RuntimeType> GetRuntimeTypes() const { return {}; } virtual std::vector<RuntimeType> GetRuntimeTypes() const { return {}; }
static const Type* CommonSupertype(const Type* a, const Type* b); static const Type* CommonSupertype(const Type* a, const Type* b);
void AddAlias(std::string alias) const { aliases_.insert(std::move(alias)); } void AddAlias(std::string alias) const { aliases_.insert(std::move(alias)); }
...@@ -258,6 +259,9 @@ class AbstractType final : public Type { ...@@ -258,6 +259,9 @@ class AbstractType final : public Type {
const std::string& name() const { return name_; } const std::string& name() const { return name_; }
std::string ToExplicitString() const override { return name(); } std::string ToExplicitString() const override { return name(); }
std::string GetGeneratedTypeNameImpl() const override { std::string GetGeneratedTypeNameImpl() const override {
if (generated_type_.empty()) {
return parent()->GetGeneratedTypeName();
}
return IsConstexpr() ? generated_type_ : "TNode<" + generated_type_ + ">"; return IsConstexpr() ? generated_type_ : "TNode<" + generated_type_ + ">";
} }
std::string GetGeneratedTNodeTypeNameImpl() const override; std::string GetGeneratedTNodeTypeNameImpl() const override;
......
...@@ -25,6 +25,9 @@ namespace torque_internal { ...@@ -25,6 +25,9 @@ namespace torque_internal {
const object: HeapObject; const object: HeapObject;
const offset: intptr; const offset: intptr;
} }
type ConstReference<T : type> extends Reference<T>;
type MutableReference<T : type> extends ConstReference<T>;
type UninitializedHeapObject extends HeapObject; type UninitializedHeapObject extends HeapObject;
} }
...@@ -42,6 +45,7 @@ extern class HeapObject extends StrongTagged { ...@@ -42,6 +45,7 @@ extern class HeapObject extends StrongTagged {
} }
type Map extends HeapObject generates 'TNode<Map>'; type Map extends HeapObject generates 'TNode<Map>';
type Object = Smi | HeapObject; type Object = Smi | HeapObject;
type Number = Smi|HeapNumber;
type JSReceiver extends HeapObject generates 'TNode<JSReceiver>'; type JSReceiver extends HeapObject generates 'TNode<JSReceiver>';
type JSObject extends JSReceiver generates 'TNode<JSObject>'; type JSObject extends JSReceiver generates 'TNode<JSObject>';
type int32 generates 'TNode<Int32T>' constexpr 'int32_t'; type int32 generates 'TNode<Int32T>' constexpr 'int32_t';
...@@ -71,12 +75,17 @@ type BuiltinPtr extends Smi generates 'TNode<BuiltinPtr>'; ...@@ -71,12 +75,17 @@ type BuiltinPtr extends Smi generates 'TNode<BuiltinPtr>';
type Context extends HeapObject generates 'TNode<Context>'; type Context extends HeapObject generates 'TNode<Context>';
type NativeContext extends Context; type NativeContext extends Context;
type SmiTagged<T : type extends uint31> extends Smi; type SmiTagged<T : type extends uint31> extends Smi;
type String extends HeapObject;
type HeapNumber extends HeapObject;
type FixedArrayBase extends HeapObject;
struct float64_or_hole { struct float64_or_hole {
is_hole: bool; is_hole: bool;
value: float64; value: float64;
} }
extern operator '+' macro IntPtrAdd(intptr, intptr): intptr;
intrinsic %FromConstexpr<To: type, From: type>(b: From): To; intrinsic %FromConstexpr<To: type, From: type>(b: From): To;
intrinsic %RawDownCast<To: type, From: type>(x: From): To; intrinsic %RawDownCast<To: type, From: type>(x: From): To;
intrinsic %RawConstexprCast<To: type, From: type>(f: From): To; intrinsic %RawConstexprCast<To: type, From: type>(f: From): To;
...@@ -85,6 +94,7 @@ extern macro TaggedToSmi(Object): Smi ...@@ -85,6 +94,7 @@ extern macro TaggedToSmi(Object): Smi
labels CastError; labels CastError;
extern macro TaggedToHeapObject(Object): HeapObject extern macro TaggedToHeapObject(Object): HeapObject
labels CastError; labels CastError;
extern macro Float64SilenceNaN(float64): float64;
extern macro IntPtrConstant(constexpr int31): intptr; extern macro IntPtrConstant(constexpr int31): intptr;
...@@ -98,6 +108,9 @@ FromConstexpr<Smi, constexpr int31>(s: constexpr int31): Smi { ...@@ -98,6 +108,9 @@ FromConstexpr<Smi, constexpr int31>(s: constexpr int31): Smi {
FromConstexpr<intptr, constexpr int31>(i: constexpr int31): intptr { FromConstexpr<intptr, constexpr int31>(i: constexpr int31): intptr {
return IntPtrConstant(i); return IntPtrConstant(i);
} }
FromConstexpr<intptr, constexpr intptr>(i: constexpr intptr): intptr {
return %FromConstexpr<intptr>(i);
}
macro Cast<A : type extends Object>(implicit context: Context)(o: Object): A macro Cast<A : type extends Object>(implicit context: Context)(o: Object): A
labels CastError { labels CastError {
...@@ -614,6 +627,134 @@ TEST(Torque, EnumInTypeswitch) { ...@@ -614,6 +627,134 @@ TEST(Torque, EnumInTypeswitch) {
)"); )");
} }
TEST(Torque, ConstClassFields) {
ExpectSuccessfulCompilation(R"(
class Foo extends HeapObject {
const x: int32;
y: int32;
}
@export
macro Test(implicit context: Context)(o: Foo, n: int32) {
const _x: int32 = o.x;
o.y = n;
}
)");
ExpectFailingCompilation(R"(
class Foo extends HeapObject {
const x: int32;
}
@export
macro Test(implicit context: Context)(o: Foo, n: int32) {
o.x = n;
}
)",
HasSubstr("cannot assign to const value"));
ExpectSuccessfulCompilation(R"(
class Foo extends HeapObject {
s: Bar;
}
struct Bar {
const x: int32;
y: int32;
}
@export
macro Test(implicit context: Context)(o: Foo, n: int32) {
const _x: int32 = o.s.x;
// Assigning a struct as a value is OK, even when the struct contains
// const fields.
o.s = Bar{x: n, y: n};
o.s.y = n;
}
)");
ExpectFailingCompilation(R"(
class Foo extends HeapObject {
const s: Bar;
}
struct Bar {
const x: int32;
y: int32;
}
@export
macro Test(implicit context: Context)(o: Foo, n: int32) {
o.s.y = n;
}
)",
HasSubstr("cannot assign to const value"));
ExpectFailingCompilation(R"(
class Foo extends HeapObject {
s: Bar;
}
struct Bar {
const x: int32;
y: int32;
}
@export
macro Test(implicit context: Context)(o: Foo, n: int32) {
o.s.x = n;
}
)",
HasSubstr("cannot assign to const value"));
}
TEST(Torque, References) {
ExpectSuccessfulCompilation(R"(
class Foo extends HeapObject {
const x: int32;
y: int32;
}
@export
macro Test(implicit context: Context)(o: Foo, n: int32) {
const constRefX: const &int32 = &o.x;
const refY: &int32 = &o.y;
const constRefY: const &int32 = refY;
const _x: int32 = *constRefX;
const _y1: int32 = *refY;
const _y2: int32 = *constRefY;
*refY = n;
let r: const &int32 = constRefX;
r = constRefY;
}
)");
ExpectFailingCompilation(R"(
class Foo extends HeapObject {
const x: int32;
y: int32;
}
@export
macro Test(implicit context: Context)(o: Foo) {
const _refX: &int32 = &o.x;
}
)",
HasSubstr("cannot use expression of type const "
"&int32 as a value of type &int32"));
ExpectFailingCompilation(R"(
class Foo extends HeapObject {
const x: int32;
y: int32;
}
@export
macro Test(implicit context: Context)(o: Foo, n: int32) {
const constRefX: const &int32 = &o.x;
*constRefX = n;
}
)",
HasSubstr("cannot assign to const value"));
}
} // namespace torque } // namespace torque
} // namespace internal } // namespace internal
} // namespace v8 } // namespace v8
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment