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

[torque] fix Torque crash when accessing fields of non-class types

When accessing a field of a non-class type, Torque will generate a
CallAccess LocationReference, which has an unknown type. We still tried
to access it's type, resulting in a DCHECK failure.

Bug: v8:7793
Change-Id: I3650643e29db852783eca1e166b700eebd1b8dc2
Reviewed-on: https://chromium-review.googlesource.com/c/v8/v8/+/2209056
Commit-Queue: Tobias Tebbi <tebbi@chromium.org>
Auto-Submit: Tobias Tebbi <tebbi@chromium.org>
Reviewed-by: 's avatarNico Hartmann <nicohartmann@chromium.org>
Cr-Commit-Position: refs/heads/master@{#68180}
parent 85539275
...@@ -2033,25 +2033,29 @@ LocationReference ImplementationVisitor::GenerateFieldAccess( ...@@ -2033,25 +2033,29 @@ LocationReference ImplementationVisitor::GenerateFieldAccess(
ProjectStructField(reference.temporary(), fieldname), ProjectStructField(reference.temporary(), fieldname),
reference.temporary_description()); reference.temporary_description());
} }
if (reference.ReferencedType()->IsBitFieldStructType()) { if (base::Optional<const Type*> referenced_type =
const BitFieldStructType* bitfield_struct = reference.ReferencedType()) {
BitFieldStructType::cast(reference.ReferencedType()); if ((*referenced_type)->IsBitFieldStructType()) {
const BitField& field = bitfield_struct->LookupField(fieldname); const BitFieldStructType* bitfield_struct =
return LocationReference::BitFieldAccess(reference, field); BitFieldStructType::cast(*referenced_type);
} const BitField& field = bitfield_struct->LookupField(fieldname);
if (const auto type_wrapped_in_smi = Type::MatchUnaryGeneric( return LocationReference::BitFieldAccess(reference, field);
reference.ReferencedType(), TypeOracle::GetSmiTaggedGeneric())) { }
const BitFieldStructType* bitfield_struct = if (const auto type_wrapped_in_smi = Type::MatchUnaryGeneric(
BitFieldStructType::DynamicCast(*type_wrapped_in_smi); (*referenced_type), TypeOracle::GetSmiTaggedGeneric())) {
if (bitfield_struct == nullptr) { const BitFieldStructType* bitfield_struct =
ReportError( BitFieldStructType::DynamicCast(*type_wrapped_in_smi);
"When a value of type SmiTagged<T> is used in a field access " if (bitfield_struct == nullptr) {
"expression, T is expected to be a bitfield struct type. Instead, T " ReportError(
"is ", "When a value of type SmiTagged<T> is used in a field access "
**type_wrapped_in_smi); "expression, T is expected to be a bitfield struct type. Instead, "
"T "
"is ",
**type_wrapped_in_smi);
}
const BitField& field = bitfield_struct->LookupField(fieldname);
return LocationReference::BitFieldAccess(reference, field);
} }
const BitField& field = bitfield_struct->LookupField(fieldname);
return LocationReference::BitFieldAccess(reference, field);
} }
if (reference.IsHeapReference()) { if (reference.IsHeapReference()) {
VisitResult ref = reference.heap_reference(); VisitResult ref = reference.heap_reference();
...@@ -2216,7 +2220,7 @@ VisitResult ImplementationVisitor::GenerateFetchFromLocation( ...@@ -2216,7 +2220,7 @@ VisitResult ImplementationVisitor::GenerateFetchFromLocation(
} else if (reference.IsVariableAccess()) { } else if (reference.IsVariableAccess()) {
return GenerateCopy(reference.variable()); return GenerateCopy(reference.variable());
} else if (reference.IsHeapReference()) { } else if (reference.IsHeapReference()) {
const Type* referenced_type = reference.ReferencedType(); const Type* referenced_type = *reference.ReferencedType();
if (referenced_type == TypeOracle::GetFloat64OrHoleType()) { if (referenced_type == TypeOracle::GetFloat64OrHoleType()) {
return GenerateCall(QualifiedName({TORQUE_INTERNAL_NAMESPACE_STRING}, return GenerateCall(QualifiedName({TORQUE_INTERNAL_NAMESPACE_STRING},
"LoadFloat64OrHole"), "LoadFloat64OrHole"),
...@@ -2233,9 +2237,9 @@ VisitResult ImplementationVisitor::GenerateFetchFromLocation( ...@@ -2233,9 +2237,9 @@ VisitResult ImplementationVisitor::GenerateFetchFromLocation(
return VisitResult(referenced_type, result_range); return VisitResult(referenced_type, result_range);
} else { } else {
GenerateCopy(reference.heap_reference()); GenerateCopy(reference.heap_reference());
assembler().Emit(LoadReferenceInstruction{reference.ReferencedType()}); assembler().Emit(LoadReferenceInstruction{referenced_type});
DCHECK_EQ(1, LoweredSlotCount(reference.ReferencedType())); DCHECK_EQ(1, LoweredSlotCount(referenced_type));
return VisitResult(reference.ReferencedType(), assembler().TopRange(1)); return VisitResult(referenced_type, assembler().TopRange(1));
} }
} else if (reference.IsBitFieldAccess()) { } else if (reference.IsBitFieldAccess()) {
// First fetch the bitfield struct, then get the bits out of it. // First fetch the bitfield struct, then get the bits out of it.
...@@ -2243,7 +2247,7 @@ VisitResult ImplementationVisitor::GenerateFetchFromLocation( ...@@ -2243,7 +2247,7 @@ VisitResult ImplementationVisitor::GenerateFetchFromLocation(
GenerateFetchFromLocation(reference.bit_field_struct_location()); GenerateFetchFromLocation(reference.bit_field_struct_location());
assembler().Emit(LoadBitFieldInstruction{bit_field_struct.type(), assembler().Emit(LoadBitFieldInstruction{bit_field_struct.type(),
reference.bit_field()}); reference.bit_field()});
return VisitResult(reference.ReferencedType(), assembler().TopRange(1)); return VisitResult(*reference.ReferencedType(), assembler().TopRange(1));
} else { } else {
if (reference.IsHeapSlice()) { if (reference.IsHeapSlice()) {
ReportError( ReportError(
...@@ -2276,7 +2280,7 @@ void ImplementationVisitor::GenerateAssignToLocation( ...@@ -2276,7 +2280,7 @@ void ImplementationVisitor::GenerateAssignToLocation(
} else if (reference.IsHeapSlice()) { } else if (reference.IsHeapSlice()) {
ReportError("assigning a value directly to an indexed field isn't allowed"); ReportError("assigning a value directly to an indexed field isn't allowed");
} else if (reference.IsHeapReference()) { } else if (reference.IsHeapReference()) {
const Type* referenced_type = reference.ReferencedType(); const Type* referenced_type = *reference.ReferencedType();
if (reference.IsConst()) { if (reference.IsConst()) {
Error("cannot assign to const value of type ", *referenced_type).Throw(); Error("cannot assign to const value of type ", *referenced_type).Throw();
} }
...@@ -2318,7 +2322,7 @@ void ImplementationVisitor::GenerateAssignToLocation( ...@@ -2318,7 +2322,7 @@ void ImplementationVisitor::GenerateAssignToLocation(
VisitResult bit_field_struct = VisitResult bit_field_struct =
GenerateFetchFromLocation(reference.bit_field_struct_location()); GenerateFetchFromLocation(reference.bit_field_struct_location());
VisitResult converted_value = VisitResult converted_value =
GenerateImplicitConvert(reference.ReferencedType(), assignment_value); GenerateImplicitConvert(*reference.ReferencedType(), assignment_value);
VisitResult updated_bit_field_struct = VisitResult updated_bit_field_struct =
GenerateSetBitField(bit_field_struct.type(), reference.bit_field(), GenerateSetBitField(bit_field_struct.type(), reference.bit_field(),
bit_field_struct, converted_value); bit_field_struct, converted_value);
...@@ -2729,7 +2733,7 @@ VisitResult ImplementationVisitor::Visit(CallMethodExpression* expr) { ...@@ -2729,7 +2733,7 @@ VisitResult ImplementationVisitor::Visit(CallMethodExpression* expr) {
target = LocationReference::Temporary(result, "this parameter"); target = LocationReference::Temporary(result, "this parameter");
} }
const AggregateType* target_type = const AggregateType* target_type =
AggregateType::DynamicCast(target.ReferencedType()); AggregateType::DynamicCast(*target.ReferencedType());
if (!target_type) { if (!target_type) {
ReportError("target of method call not a struct or class type"); ReportError("target of method call not a struct or class type");
} }
......
...@@ -137,7 +137,7 @@ class LocationReference { ...@@ -137,7 +137,7 @@ class LocationReference {
return *bit_field_; return *bit_field_;
} }
const Type* ReferencedType() const { base::Optional<const Type*> ReferencedType() const {
if (IsHeapReference()) { if (IsHeapReference()) {
return *TypeOracle::MatchReferenceGeneric(heap_reference().type()); return *TypeOracle::MatchReferenceGeneric(heap_reference().type());
} }
...@@ -148,7 +148,10 @@ class LocationReference { ...@@ -148,7 +148,10 @@ class LocationReference {
if (IsBitFieldAccess()) { if (IsBitFieldAccess()) {
return bit_field_->name_and_type.type; return bit_field_->name_and_type.type;
} }
return GetVisitResult().type(); if (IsVariableAccess() || IsHeapSlice() || IsTemporary()) {
return GetVisitResult().type();
}
return base::nullopt;
} }
const VisitResult& GetVisitResult() const { const VisitResult& GetVisitResult() const {
......
...@@ -829,6 +829,17 @@ TEST(Torque, BitFieldLogicalAnd) { ...@@ -829,6 +829,17 @@ TEST(Torque, BitFieldLogicalAnd) {
HasSubstr(message)); HasSubstr(message));
} }
TEST(Torque, FieldAccessOnNonClassType) {
ExpectFailingCompilation(
R"(
@export
macro Test(x: Number): Map {
return x.map;
}
)",
HasSubstr("map"));
}
} // 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