Commit 57074692 authored by Seth Brenith's avatar Seth Brenith Committed by Commit Bot

[torque] Add bitfield declarations

This change is the first part of adding Torque support for a "bitfield
struct", which represents a set of bitfields packed together into an
integer value. With this change, Torque can generate the list of
BitField template specializations that allow runtime code to use the
bitfield values. The flags used in SharedFunctionInfo are converted to
Torque to exercise this functionality. Bitfield values are not yet
accessible directly from Torque code.

Bug: v8:7793
Change-Id: I9e4a3df7c847111b6e02e513f175dbf938b0be35
Reviewed-on: https://chromium-review.googlesource.com/c/v8/v8/+/1949047
Commit-Queue: Seth Brenith <seth.brenith@microsoft.com>
Reviewed-by: 's avatarTobias Tebbi <tebbi@chromium.org>
Reviewed-by: 's avatarNico Hartmann <nicohartmann@chromium.org>
Cr-Commit-Position: refs/heads/master@{#65371}
parent 31e9ebee
...@@ -188,7 +188,7 @@ BIT_FIELD_ACCESSORS(SharedFunctionInfo, flags, is_asm_wasm_broken, ...@@ -188,7 +188,7 @@ BIT_FIELD_ACCESSORS(SharedFunctionInfo, flags, is_asm_wasm_broken,
SharedFunctionInfo::IsAsmWasmBrokenBit) SharedFunctionInfo::IsAsmWasmBrokenBit)
BIT_FIELD_ACCESSORS(SharedFunctionInfo, flags, BIT_FIELD_ACCESSORS(SharedFunctionInfo, flags,
requires_instance_members_initializer, requires_instance_members_initializer,
SharedFunctionInfo::RequiresInstanceMembersInitializer) SharedFunctionInfo::RequiresInstanceMembersInitializerBit)
BIT_FIELD_ACCESSORS(SharedFunctionInfo, flags, name_should_print_as_anonymous, BIT_FIELD_ACCESSORS(SharedFunctionInfo, flags, name_should_print_as_anonymous,
SharedFunctionInfo::NameShouldPrintAsAnonymousBit) SharedFunctionInfo::NameShouldPrintAsAnonymousBit)
...@@ -199,7 +199,7 @@ BIT_FIELD_ACCESSORS(SharedFunctionInfo, flags, is_toplevel, ...@@ -199,7 +199,7 @@ BIT_FIELD_ACCESSORS(SharedFunctionInfo, flags, is_toplevel,
SharedFunctionInfo::IsTopLevelBit) SharedFunctionInfo::IsTopLevelBit)
BIT_FIELD_ACCESSORS(SharedFunctionInfo, flags, BIT_FIELD_ACCESSORS(SharedFunctionInfo, flags,
is_oneshot_iife_or_properties_are_final, is_oneshot_iife_or_properties_are_final,
SharedFunctionInfo::IsOneshotIIFEOrPropertiesAreFinalBit) SharedFunctionInfo::IsOneshotIifeOrPropertiesAreFinalBit)
BIT_FIELD_ACCESSORS(SharedFunctionInfo, flags, BIT_FIELD_ACCESSORS(SharedFunctionInfo, flags,
is_safe_to_skip_arguments_adaptor, is_safe_to_skip_arguments_adaptor,
SharedFunctionInfo::IsSafeToSkipArgumentsAdaptorBit) SharedFunctionInfo::IsSafeToSkipArgumentsAdaptorBit)
......
...@@ -18,6 +18,7 @@ ...@@ -18,6 +18,7 @@
#include "src/objects/smi.h" #include "src/objects/smi.h"
#include "src/objects/struct.h" #include "src/objects/struct.h"
#include "testing/gtest/include/gtest/gtest_prod.h" #include "testing/gtest/include/gtest/gtest_prod.h"
#include "torque-generated/bit-fields-tq.h"
#include "torque-generated/field-offsets-tq.h" #include "torque-generated/field-offsets-tq.h"
// Has to be the last include (doesn't have include guards): // Has to be the last include (doesn't have include guards):
...@@ -165,7 +166,8 @@ class InterpreterData : public Struct { ...@@ -165,7 +166,8 @@ class InterpreterData : public Struct {
// SharedFunctionInfo describes the JSFunction information that can be // SharedFunctionInfo describes the JSFunction information that can be
// shared by multiple instances of the function. // shared by multiple instances of the function.
class SharedFunctionInfo : public HeapObject { class SharedFunctionInfo : public HeapObject,
public TorqueGeneratedSharedFunctionInfoFlagsFields {
public: public:
NEVER_READ_ONLY_SPACE NEVER_READ_ONLY_SPACE
...@@ -616,31 +618,6 @@ class SharedFunctionInfo : public HeapObject { ...@@ -616,31 +618,6 @@ class SharedFunctionInfo : public HeapObject {
class BodyDescriptor; class BodyDescriptor;
// Bit positions in |flags|.
#define FLAGS_BIT_FIELDS(V, _) \
/* Have FunctionKind first to make it cheaper to access */ \
V(FunctionKindBits, FunctionKind, 5, _) \
V(IsNativeBit, bool, 1, _) \
V(IsStrictBit, bool, 1, _) \
V(FunctionSyntaxKindBits, FunctionSyntaxKind, 3, _) \
V(IsClassConstructorBit, bool, 1, _) \
V(HasDuplicateParametersBit, bool, 1, _) \
V(AllowLazyCompilationBit, bool, 1, _) \
V(NeedsHomeObjectBit, bool, 1, _) \
V(IsAsmWasmBrokenBit, bool, 1, _) \
V(FunctionMapIndexBits, int, 5, _) \
V(DisabledOptimizationReasonBits, BailoutReason, 4, _) \
V(RequiresInstanceMembersInitializer, bool, 1, _) \
V(ConstructAsBuiltinBit, bool, 1, _) \
V(NameShouldPrintAsAnonymousBit, bool, 1, _) \
V(HasReportedBinaryCoverageBit, bool, 1, _) \
V(IsTopLevelBit, bool, 1, _) \
V(IsOneshotIIFEOrPropertiesAreFinalBit, bool, 1, _) \
V(IsSafeToSkipArgumentsAdaptorBit, bool, 1, _) \
V(PrivateNameLookupSkipsOuterClassBit, bool, 1, _)
DEFINE_BIT_FIELDS(FLAGS_BIT_FIELDS)
#undef FLAGS_BIT_FIELDS
// Bailout reasons must fit in the DisabledOptimizationReason bitfield. // Bailout reasons must fit in the DisabledOptimizationReason bitfield.
STATIC_ASSERT(BailoutReason::kLastErrorMessage <= STATIC_ASSERT(BailoutReason::kLastErrorMessage <=
DisabledOptimizationReasonBits::kMax); DisabledOptimizationReasonBits::kMax);
......
...@@ -14,6 +14,34 @@ extern class InterpreterData extends Struct { ...@@ -14,6 +14,34 @@ extern class InterpreterData extends Struct {
interpreter_trampoline: Code; interpreter_trampoline: Code;
} }
type FunctionKind extends uint8 constexpr 'v8::internal::FunctionKind';
type FunctionSyntaxKind extends uint8
constexpr 'v8::internal::FunctionSyntaxKind';
type BailoutReason extends uint8 constexpr 'v8::internal::BailoutReason';
bitfield struct SharedFunctionInfoFlags extends uint32 {
// Have FunctionKind first to make it cheaper to access.
function_kind: FunctionKind: 5 bit;
is_native: bool: 1 bit;
is_strict: bool: 1 bit;
function_syntax_kind: FunctionSyntaxKind: 3 bit;
is_class_constructor: bool: 1 bit;
has_duplicate_parameters: bool: 1 bit;
allow_lazy_compilation: bool: 1 bit;
needs_home_object: bool: 1 bit;
is_asm_wasm_broken: bool: 1 bit;
function_map_index: int32: 5 bit;
disabled_optimization_reason: BailoutReason: 4 bit;
requires_instance_members_initializer: bool: 1 bit;
construct_as_builtin: bool: 1 bit;
name_should_print_as_anonymous: bool: 1 bit;
has_reported_binary_coverage: bool: 1 bit;
is_top_level: bool: 1 bit;
is_oneshot_iife_or_properties_are_final: bool: 1 bit;
is_safe_to_skip_arguments_adaptor: bool: 1 bit;
private_name_lookup_skips_outer_class: bool: 1 bit;
}
extern class SharedFunctionInfo extends HeapObject { extern class SharedFunctionInfo extends HeapObject {
weak function_data: Object; weak function_data: Object;
name_or_scope_info: String|NoSharedNameSentinel|ScopeInfo; name_or_scope_info: String|NoSharedNameSentinel|ScopeInfo;
...@@ -24,7 +52,7 @@ extern class SharedFunctionInfo extends HeapObject { ...@@ -24,7 +52,7 @@ extern class SharedFunctionInfo extends HeapObject {
// Currently set to uint16, can be set to uint8 to save space. // Currently set to uint16, can be set to uint8 to save space.
expected_nof_properties: uint16; expected_nof_properties: uint16;
function_token_offset: int16; function_token_offset: int16;
flags: int32; flags: SharedFunctionInfoFlags;
function_literal_id: int32; function_literal_id: int32;
@if(V8_SFI_HAS_UNIQUE_ID) unique_id: int32; @if(V8_SFI_HAS_UNIQUE_ID) unique_id: int32;
} }
......
...@@ -66,6 +66,7 @@ namespace torque { ...@@ -66,6 +66,7 @@ namespace torque {
#define AST_TYPE_DECLARATION_NODE_KIND_LIST(V) \ #define AST_TYPE_DECLARATION_NODE_KIND_LIST(V) \
V(AbstractTypeDeclaration) \ V(AbstractTypeDeclaration) \
V(TypeAliasDeclaration) \ V(TypeAliasDeclaration) \
V(BitFieldStructDeclaration) \
V(ClassDeclaration) \ V(ClassDeclaration) \
V(StructDeclaration) V(StructDeclaration)
...@@ -839,6 +840,11 @@ struct StructFieldExpression { ...@@ -839,6 +840,11 @@ struct StructFieldExpression {
bool const_qualified; bool const_qualified;
}; };
struct BitFieldDeclaration {
NameAndTypeExpression name_and_type;
int num_bits;
};
enum class ConditionalAnnotationType { enum class ConditionalAnnotationType {
kPositive, kPositive,
kNegative, kNegative,
...@@ -849,9 +855,15 @@ struct ConditionalAnnotation { ...@@ -849,9 +855,15 @@ struct ConditionalAnnotation {
ConditionalAnnotationType type; ConditionalAnnotationType type;
}; };
struct AnnotationParameter {
std::string string_value;
int int_value;
bool is_int;
};
struct Annotation { struct Annotation {
Identifier* name; Identifier* name;
base::Optional<std::string> param; base::Optional<AnnotationParameter> param;
}; };
struct ClassFieldExpression { struct ClassFieldExpression {
...@@ -1101,6 +1113,18 @@ struct StructDeclaration : TypeDeclaration { ...@@ -1101,6 +1113,18 @@ struct StructDeclaration : TypeDeclaration {
std::vector<StructFieldExpression> fields; std::vector<StructFieldExpression> fields;
}; };
struct BitFieldStructDeclaration : TypeDeclaration {
DEFINE_AST_NODE_LEAF_BOILERPLATE(BitFieldStructDeclaration)
BitFieldStructDeclaration(SourcePosition pos, Identifier* name,
TypeExpression* parent,
std::vector<BitFieldDeclaration> fields)
: TypeDeclaration(kKind, pos, name),
parent(parent),
fields(std::move(fields)) {}
TypeExpression* parent;
std::vector<BitFieldDeclaration> fields;
};
struct ClassBody : AstNode { struct ClassBody : AstNode {
DEFINE_AST_NODE_LEAF_BOILERPLATE(ClassBody) DEFINE_AST_NODE_LEAF_BOILERPLATE(ClassBody)
ClassBody(SourcePosition pos, std::vector<Declaration*> methods, ClassBody(SourcePosition pos, std::vector<Declaration*> methods,
......
...@@ -81,15 +81,7 @@ class DebugFieldType { ...@@ -81,15 +81,7 @@ class DebugFieldType {
? (*field_class_type)->GetGeneratedTNodeTypeName() ? (*field_class_type)->GetGeneratedTNodeTypeName()
: "Object"); : "Object");
} }
const Type* constexpr_version = return field_.name_and_type.type->GetConstexprGeneratedTypeName();
field_.name_and_type.type->ConstexprVersion();
if (constexpr_version == nullptr) {
Error("Type '", field_.name_and_type.type->ToString(),
"' requires a constexpr representation")
.Position(field_.pos);
return "";
}
return constexpr_version->GetGeneratedTypeName();
} }
// Returns the field's size in bytes. // Returns the field's size in bytes.
...@@ -288,13 +280,7 @@ void GenerateGetPropsChunkForField(const Field& field, ...@@ -288,13 +280,7 @@ void GenerateGetPropsChunkForField(const Field& field,
count_value = count_value =
"i::PlatformSmiTagging::SmiToInt(indexed_field_count.value)"; "i::PlatformSmiTagging::SmiToInt(indexed_field_count.value)";
} else if (!index_type->IsSubtypeOf(TypeOracle::GetTaggedType())) { } else if (!index_type->IsSubtypeOf(TypeOracle::GetTaggedType())) {
const Type* constexpr_index = index_type->ConstexprVersion(); index_type_name = index_type->GetConstexprGeneratedTypeName();
if (constexpr_index == nullptr) {
Error("Type '", index_type->ToString(),
"' requires a constexpr representation");
return;
}
index_type_name = constexpr_index->GetGeneratedTypeName();
count_value = "indexed_field_count.value"; count_value = "indexed_field_count.value";
} else { } else {
Error("Unsupported index type: ", index_type); Error("Unsupported index type: ", index_type);
......
...@@ -43,6 +43,7 @@ class ParseResultHolderBase { ...@@ -43,6 +43,7 @@ class ParseResultHolderBase {
enum class ParseResultHolderBase::TypeId { enum class ParseResultHolderBase::TypeId {
kStdString, kStdString,
kBool, kBool,
kInt32,
kStdVectorOfString, kStdVectorOfString,
kExpressionPtr, kExpressionPtr,
kIdentifierPtr, kIdentifierPtr,
...@@ -59,12 +60,16 @@ enum class ParseResultHolderBase::TypeId { ...@@ -59,12 +60,16 @@ enum class ParseResultHolderBase::TypeId {
kNameAndExpression, kNameAndExpression,
kAnnotation, kAnnotation,
kVectorOfAnnotation, kVectorOfAnnotation,
kAnnotationParameter,
kOptionalAnnotationParameter,
kClassFieldExpression, kClassFieldExpression,
kStructFieldExpression, kStructFieldExpression,
kBitFieldDeclaration,
kStdVectorOfNameAndTypeExpression, kStdVectorOfNameAndTypeExpression,
kStdVectorOfNameAndExpression, kStdVectorOfNameAndExpression,
kStdVectorOfClassFieldExpression, kStdVectorOfClassFieldExpression,
kStdVectorOfStructFieldExpression, kStdVectorOfStructFieldExpression,
kStdVectorOfBitFieldDeclaration,
kIncrementDecrementOperator, kIncrementDecrementOperator,
kOptionalStdString, kOptionalStdString,
kStdVectorOfStatementPtr, kStdVectorOfStatementPtr,
......
...@@ -3075,6 +3075,44 @@ void ImplementationVisitor::GenerateClassFieldOffsets( ...@@ -3075,6 +3075,44 @@ void ImplementationVisitor::GenerateClassFieldOffsets(
WriteFile(output_header_path, header.str()); WriteFile(output_header_path, header.str());
} }
void ImplementationVisitor::GenerateBitFields(
const std::string& output_directory) {
std::stringstream header;
std::string file_name = "bit-fields-tq.h";
{
IncludeGuardScope include_guard(header, file_name);
header << "#include \"src/base/bit-field.h\"\n\n";
NamespaceScope namespaces(header, {"v8", "internal"});
// TODO(v8:7793): Once we can define enums in Torque, we should be able to
// do something nicer than hard-coding these predeclarations. Until then,
// any enum used as a bitfield must be included in this list.
header << R"(
enum class FunctionSyntaxKind : uint8_t;
enum class BailoutReason : uint8_t;
enum FunctionKind : uint8_t;
)";
for (const auto& type : TypeOracle::GetBitFieldStructTypes()) {
header << "struct TorqueGenerated" << type->name() << "Fields {\n";
std::string type_name = type->GetConstexprGeneratedTypeName();
for (const auto& field : type->fields()) {
const char* suffix = field.num_bits == 1 ? "Bit" : "Bits";
std::string field_type_name =
field.name_and_type.type->GetConstexprGeneratedTypeName();
header << " using " << CamelifyString(field.name_and_type.name)
<< suffix << " = base::BitField<" << field_type_name << ", "
<< field.offset << ", " << field.num_bits << ", " << type_name
<< ">;\n";
}
header << "};\n\n";
}
}
const std::string output_header_path = output_directory + "/" + file_name;
WriteFile(output_header_path, header.str());
}
namespace { namespace {
class ClassFieldOffsetGenerator : public FieldOffsetsGenerator { class ClassFieldOffsetGenerator : public FieldOffsetsGenerator {
...@@ -3779,7 +3817,7 @@ void ImplementationVisitor::GenerateCSATypes( ...@@ -3779,7 +3817,7 @@ void ImplementationVisitor::GenerateCSATypes(
// Generates headers for all structs in a topologically-sorted order, since // Generates headers for all structs in a topologically-sorted order, since
// TypeOracle keeps them in the order of their resolution // TypeOracle keeps them in the order of their resolution
for (auto& type : *TypeOracle::GetAggregateTypes()) { for (const auto& type : TypeOracle::GetAggregateTypes()) {
const StructType* struct_type = StructType::DynamicCast(type.get()); const StructType* struct_type = StructType::DynamicCast(type.get());
if (!struct_type) continue; if (!struct_type) continue;
h_contents << "struct " << struct_type->GetGeneratedTypeNameImpl() h_contents << "struct " << struct_type->GetGeneratedTypeNameImpl()
......
...@@ -347,6 +347,7 @@ class ImplementationVisitor { ...@@ -347,6 +347,7 @@ class ImplementationVisitor {
void GenerateBuiltinDefinitionsAndInterfaceDescriptors( void GenerateBuiltinDefinitionsAndInterfaceDescriptors(
const std::string& output_directory); const std::string& output_directory);
void GenerateClassFieldOffsets(const std::string& output_directory); void GenerateClassFieldOffsets(const std::string& output_directory);
void GenerateBitFields(const std::string& output_directory);
void GeneratePrintDefinitions(const std::string& output_directory); void GeneratePrintDefinitions(const std::string& output_directory);
void GenerateClassDefinitions(const std::string& output_directory); void GenerateClassDefinitions(const std::string& output_directory);
void GenerateInstanceTypes(const std::string& output_directory); void GenerateInstanceTypes(const std::string& output_directory);
......
...@@ -82,6 +82,7 @@ void CompileCurrentAst(TorqueCompilerOptions options) { ...@@ -82,6 +82,7 @@ void CompileCurrentAst(TorqueCompilerOptions options) {
implementation_visitor.GenerateBuiltinDefinitionsAndInterfaceDescriptors( implementation_visitor.GenerateBuiltinDefinitionsAndInterfaceDescriptors(
output_directory); output_directory);
implementation_visitor.GenerateClassFieldOffsets(output_directory); implementation_visitor.GenerateClassFieldOffsets(output_directory);
implementation_visitor.GenerateBitFields(output_directory);
implementation_visitor.GeneratePrintDefinitions(output_directory); implementation_visitor.GeneratePrintDefinitions(output_directory);
implementation_visitor.GenerateClassDefinitions(output_directory); implementation_visitor.GenerateClassDefinitions(output_directory);
implementation_visitor.GenerateClassVerifiers(output_directory); implementation_visitor.GenerateClassVerifiers(output_directory);
......
This diff is collapsed.
...@@ -12,9 +12,15 @@ namespace torque { ...@@ -12,9 +12,15 @@ namespace torque {
DEFINE_CONTEXTUAL_VARIABLE(TypeOracle) DEFINE_CONTEXTUAL_VARIABLE(TypeOracle)
// static // static
const std::vector<std::unique_ptr<AggregateType>>* const std::vector<std::unique_ptr<AggregateType>>&
TypeOracle::GetAggregateTypes() { TypeOracle::GetAggregateTypes() {
return &Get().aggregate_types_; return Get().aggregate_types_;
}
// static
const std::vector<std::unique_ptr<BitFieldStructType>>&
TypeOracle::GetBitFieldStructTypes() {
return Get().bit_field_struct_types_;
} }
// static // static
......
...@@ -43,6 +43,15 @@ class TypeOracle : public ContextualClass<TypeOracle> { ...@@ -43,6 +43,15 @@ class TypeOracle : public ContextualClass<TypeOracle> {
return result; return result;
} }
static BitFieldStructType* GetBitFieldStructType(
const Type* parent, const BitFieldStructDeclaration* decl) {
auto ptr = std::unique_ptr<BitFieldStructType>(
new BitFieldStructType(CurrentNamespace(), parent, decl));
BitFieldStructType* result = ptr.get();
Get().bit_field_struct_types_.push_back(std::move(ptr));
return result;
}
static ClassType* GetClassType(const Type* parent, const std::string& name, static ClassType* GetClassType(const Type* parent, const std::string& name,
ClassFlags flags, const std::string& generates, ClassFlags flags, const std::string& generates,
ClassDeclaration* decl, ClassDeclaration* decl,
...@@ -275,7 +284,9 @@ class TypeOracle : public ContextualClass<TypeOracle> { ...@@ -275,7 +284,9 @@ class TypeOracle : public ContextualClass<TypeOracle> {
return false; return false;
} }
static const std::vector<std::unique_ptr<AggregateType>>* GetAggregateTypes(); static const std::vector<std::unique_ptr<AggregateType>>& GetAggregateTypes();
static const std::vector<std::unique_ptr<BitFieldStructType>>&
GetBitFieldStructTypes();
static void FinalizeAggregateTypes(); static void FinalizeAggregateTypes();
...@@ -293,6 +304,7 @@ class TypeOracle : public ContextualClass<TypeOracle> { ...@@ -293,6 +304,7 @@ class TypeOracle : public ContextualClass<TypeOracle> {
Deduplicator<UnionType> union_types_; Deduplicator<UnionType> union_types_;
std::vector<std::unique_ptr<Type>> nominal_types_; std::vector<std::unique_ptr<Type>> nominal_types_;
std::vector<std::unique_ptr<AggregateType>> aggregate_types_; std::vector<std::unique_ptr<AggregateType>> aggregate_types_;
std::vector<std::unique_ptr<BitFieldStructType>> bit_field_struct_types_;
std::vector<std::unique_ptr<Type>> top_types_; std::vector<std::unique_ptr<Type>> top_types_;
std::vector<std::unique_ptr<Namespace>> std::vector<std::unique_ptr<Namespace>>
generic_type_instantiation_namespaces_; generic_type_instantiation_namespaces_;
......
...@@ -131,6 +131,70 @@ void DeclareMethods(AggregateType* container_type, ...@@ -131,6 +131,70 @@ void DeclareMethods(AggregateType* container_type,
} }
} }
const BitFieldStructType* TypeVisitor::ComputeType(
BitFieldStructDeclaration* decl, MaybeSpecializationKey specialized_from) {
CurrentSourcePosition::Scope position_scope(decl->pos);
if (specialized_from.has_value()) {
ReportError("Bitfield struct specialization is not supported");
}
const Type* parent = TypeVisitor::ComputeType(decl->parent);
if (!IsAnyUnsignedInteger(parent)) {
ReportError(
"Bitfield struct must extend from an unsigned integer type, not ",
parent->ToString());
}
auto opt_size = SizeOf(parent);
if (!opt_size.has_value()) {
ReportError("Cannot determine size of bitfield struct ", decl->name->value,
" because of unsized parent type ", parent->ToString());
}
const size_t size = 8 * std::get<0>(*opt_size); // Convert bytes to bits.
BitFieldStructType* type = TypeOracle::GetBitFieldStructType(parent, decl);
// Iterate through all of the declared fields, checking their validity and
// registering them on the newly-constructed BitFieldStructType instance.
int offset = 0;
for (const auto& field : decl->fields) {
CurrentSourcePosition::Scope field_position_scope(
field.name_and_type.type->pos);
const Type* field_type = TypeVisitor::ComputeType(field.name_and_type.type);
if (!IsAllowedAsBitField(field_type)) {
ReportError("Type not allowed as bitfield: ",
field.name_and_type.name->value);
}
// Compute the maximum number of bits that could be used for a field of this
// type. Booleans are a special case, not included in SizeOf, because their
// runtime size is 32 bits but they should only occupy 1 bit as a bitfield.
size_t field_type_size = 0;
if (field_type == TypeOracle::GetBoolType()) {
field_type_size = 1;
} else {
auto opt_field_type_size = SizeOf(field_type);
if (!opt_field_type_size.has_value()) {
ReportError("Size unknown for type ", field_type->ToString());
}
field_type_size = 8 * std::get<0>(*opt_field_type_size);
}
if (field.num_bits < 1 ||
static_cast<size_t>(field.num_bits) > field_type_size) {
ReportError("Invalid number of bits for ",
field.name_and_type.name->value);
}
type->RegisterField({field.name_and_type.name->pos,
{field.name_and_type.name->value, field_type},
offset,
field.num_bits});
offset += field.num_bits;
if (static_cast<size_t>(offset) > size) {
ReportError("Too many total bits in ", decl->name->value);
}
}
return type;
}
const StructType* TypeVisitor::ComputeType( const StructType* TypeVisitor::ComputeType(
StructDeclaration* decl, MaybeSpecializationKey specialized_from) { StructDeclaration* decl, MaybeSpecializationKey specialized_from) {
StructType* struct_type = TypeOracle::GetStructType(decl, specialized_from); StructType* struct_type = TypeOracle::GetStructType(decl, specialized_from);
......
...@@ -47,6 +47,8 @@ class TypeVisitor { ...@@ -47,6 +47,8 @@ class TypeVisitor {
AbstractTypeDeclaration* decl, MaybeSpecializationKey specialized_from); AbstractTypeDeclaration* decl, MaybeSpecializationKey specialized_from);
static const Type* ComputeType(TypeAliasDeclaration* decl, static const Type* ComputeType(TypeAliasDeclaration* decl,
MaybeSpecializationKey specialized_from); MaybeSpecializationKey specialized_from);
static const BitFieldStructType* ComputeType(
BitFieldStructDeclaration* decl, MaybeSpecializationKey specialized_from);
static const StructType* ComputeType(StructDeclaration* decl, static const StructType* ComputeType(StructDeclaration* decl,
MaybeSpecializationKey specialized_from); MaybeSpecializationKey specialized_from);
static const ClassType* ComputeType(ClassDeclaration* decl, static const ClassType* ComputeType(ClassDeclaration* decl,
......
...@@ -76,6 +76,15 @@ bool Type::IsSubtypeOf(const Type* supertype) const { ...@@ -76,6 +76,15 @@ bool Type::IsSubtypeOf(const Type* supertype) const {
return false; return false;
} }
std::string Type::GetConstexprGeneratedTypeName() const {
const Type* constexpr_version = ConstexprVersion();
if (constexpr_version == nullptr) {
Error("Type '", ToString(), "' requires a constexpr representation");
return "";
}
return constexpr_version->GetGeneratedTypeName();
}
base::Optional<const ClassType*> Type::ClassSupertype() const { base::Optional<const ClassType*> Type::ClassSupertype() const {
for (const Type* t = this; t != nullptr; t = t->parent()) { for (const Type* t = this; t != nullptr; t = t->parent()) {
if (auto* class_type = ClassType::DynamicCast(t)) { if (auto* class_type = ClassType::DynamicCast(t)) {
...@@ -245,6 +254,10 @@ const Type* SubtractType(const Type* a, const Type* b) { ...@@ -245,6 +254,10 @@ const Type* SubtractType(const Type* a, const Type* b) {
return TypeOracle::GetUnionType(result); return TypeOracle::GetUnionType(result);
} }
std::string BitFieldStructType::ToExplicitString() const {
return "bitfield struct " + name();
}
void AggregateType::CheckForDuplicateFields() const { void AggregateType::CheckForDuplicateFields() const {
// Check the aggregate hierarchy and currently defined class for duplicate // Check the aggregate hierarchy and currently defined class for duplicate
// field declarations. // field declarations.
...@@ -401,11 +414,7 @@ std::vector<Method*> AggregateType::Methods(const std::string& name) const { ...@@ -401,11 +414,7 @@ std::vector<Method*> AggregateType::Methods(const std::string& name) const {
return result; return result;
} }
std::string StructType::ToExplicitString() const { std::string StructType::ToExplicitString() const { return "struct " + name(); }
std::stringstream result;
result << "struct " << name();
return result.str();
}
void StructType::Finalize() const { void StructType::Finalize() const {
if (is_finalized_) return; if (is_finalized_) return;
...@@ -447,11 +456,7 @@ std::string ClassType::GetGeneratedTypeNameImpl() const { ...@@ -447,11 +456,7 @@ std::string ClassType::GetGeneratedTypeNameImpl() const {
: "TNode<" + GetGeneratedTNodeTypeName() + ">"; : "TNode<" + GetGeneratedTNodeTypeName() + ">";
} }
std::string ClassType::ToExplicitString() const { std::string ClassType::ToExplicitString() const { return "class " + name(); }
std::stringstream result;
result << "class " << name();
return result.str();
}
bool ClassType::AllowInstantiation() const { bool ClassType::AllowInstantiation() const {
return (!IsExtern() || nspace()->IsDefaultNamespace()) && !IsAbstract(); return (!IsExtern() || nspace()->IsDefaultNamespace()) && !IsAbstract();
...@@ -774,6 +779,28 @@ base::Optional<std::tuple<size_t, std::string>> SizeOf(const Type* type) { ...@@ -774,6 +779,28 @@ base::Optional<std::tuple<size_t, std::string>> SizeOf(const Type* type) {
return std::make_tuple(size, size_string); return std::make_tuple(size, size_string);
} }
bool IsAnyUnsignedInteger(const Type* type) {
return type == TypeOracle::GetUint32Type() ||
type == TypeOracle::GetUint16Type() ||
type == TypeOracle::GetUint8Type() ||
type == TypeOracle::GetUIntPtrType();
}
bool IsAllowedAsBitField(const Type* type) {
if (type->IsBitFieldStructType()) {
// No nested bitfield structs for now. We could reconsider if there's a
// compelling use case.
return false;
}
// Any integer-ish type, including bools and enums which inherit from integer
// types, are allowed.
return type->IsSubtypeOf(TypeOracle::GetUint32Type()) ||
type->IsSubtypeOf(TypeOracle::GetUIntPtrType()) ||
type->IsSubtypeOf(TypeOracle::GetInt32Type()) ||
type->IsSubtypeOf(TypeOracle::GetIntPtrType()) ||
type->IsSubtypeOf(TypeOracle::GetBoolType());
}
} // namespace torque } // namespace torque
} // namespace internal } // namespace internal
} // namespace v8 } // namespace v8
...@@ -39,6 +39,7 @@ class TypeBase { ...@@ -39,6 +39,7 @@ class TypeBase {
kAbstractType, kAbstractType,
kBuiltinPointerType, kBuiltinPointerType,
kUnionType, kUnionType,
kBitFieldStructType,
kStructType, kStructType,
kClassType kClassType
}; };
...@@ -49,6 +50,9 @@ class TypeBase { ...@@ -49,6 +50,9 @@ class TypeBase {
return kind() == Kind::kBuiltinPointerType; return kind() == Kind::kBuiltinPointerType;
} }
bool IsUnionType() const { return kind() == Kind::kUnionType; } bool IsUnionType() const { return kind() == Kind::kUnionType; }
bool IsBitFieldStructType() const {
return kind() == Kind::kBitFieldStructType;
}
bool IsStructType() const { return kind() == Kind::kStructType; } bool IsStructType() const { return kind() == Kind::kStructType; }
bool IsClassType() const { return kind() == Kind::kClassType; } bool IsClassType() const { return kind() == Kind::kClassType; }
bool IsAggregateType() const { return IsStructType() || IsClassType(); } bool IsAggregateType() const { return IsStructType() || IsClassType(); }
...@@ -125,6 +129,7 @@ class V8_EXPORT_PRIVATE Type : public TypeBase { ...@@ -125,6 +129,7 @@ class V8_EXPORT_PRIVATE Type : public TypeBase {
virtual bool IsTransient() const { return false; } virtual bool IsTransient() const { return false; }
virtual const Type* NonConstexprVersion() const { return this; } virtual const Type* NonConstexprVersion() const { return this; }
virtual const Type* ConstexprVersion() const { return nullptr; } virtual const Type* ConstexprVersion() const { return nullptr; }
std::string GetConstexprGeneratedTypeName() const;
base::Optional<const ClassType*> ClassSupertype() const; base::Optional<const ClassType*> ClassSupertype() 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);
...@@ -445,6 +450,51 @@ class V8_EXPORT_PRIVATE UnionType final : public Type { ...@@ -445,6 +450,51 @@ class V8_EXPORT_PRIVATE UnionType final : public Type {
const Type* SubtractType(const Type* a, const Type* b); const Type* SubtractType(const Type* a, const Type* b);
struct BitField {
SourcePosition pos;
NameAndType name_and_type;
int offset;
int num_bits;
};
class V8_EXPORT_PRIVATE BitFieldStructType final : public Type {
public:
DECLARE_TYPE_BOILERPLATE(BitFieldStructType)
std::string ToExplicitString() const override;
std::string GetGeneratedTypeNameImpl() const override {
return parent()->GetGeneratedTypeName();
}
std::string GetGeneratedTNodeTypeNameImpl() const override {
return parent()->GetGeneratedTNodeTypeName();
}
std::vector<RuntimeType> GetRuntimeTypes() const override {
return {{parent()->GetGeneratedTNodeTypeName(), ""}};
}
const Type* ConstexprVersion() const override {
return parent()->ConstexprVersion();
}
void RegisterField(BitField field) { fields_.push_back(std::move(field)); }
const std::string& name() const { return decl_->name->value; }
const std::vector<BitField>& fields() const { return fields_; }
private:
friend class TypeOracle;
BitFieldStructType(Namespace* nspace, const Type* parent,
const BitFieldStructDeclaration* decl)
: Type(Kind::kBitFieldStructType, parent),
namespace_(nspace),
decl_(decl) {}
std::string SimpleNameImpl() const override { return name(); }
Namespace* namespace_;
const BitFieldStructDeclaration* decl_;
std::vector<BitField> fields_;
};
class AggregateType : public Type { class AggregateType : public Type {
public: public:
DECLARE_TYPE_BOILERPLATE(AggregateType) DECLARE_TYPE_BOILERPLATE(AggregateType)
...@@ -729,6 +779,8 @@ TypeVector LowerParameterTypes(const ParameterTypes& parameter_types, ...@@ -729,6 +779,8 @@ TypeVector LowerParameterTypes(const ParameterTypes& parameter_types,
size_t vararg_count = 0); size_t vararg_count = 0);
base::Optional<std::tuple<size_t, std::string>> SizeOf(const Type* type); base::Optional<std::tuple<size_t, std::string>> SizeOf(const Type* type);
bool IsAnyUnsignedInteger(const Type* type);
bool IsAllowedAsBitField(const Type* type);
} // namespace torque } // namespace torque
} // namespace internal } // namespace internal
......
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