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

[torque] generate implicit_cast according to VisitResult types

In the generated CSA, we called overloaded macros while relying on CSA
subtyping of TNodes. This doesn't work well with overloads, because
for C++ any TNode subtyping is treated as an implicit conversion, which
makes these calls ambiguous for C++.
As a solution, we insert implicit_cast conversions for arguments
according to the type predicted by Torque. This way, a CSA overload is always
called with exactly the signature declared in base.tq.
This has the additional benefit that it validates the signatures declared in
base.tq, which could previously be too permissive.
Also, this triggered a bug in structs, where VisitResult's were
carrying the wrong type.

Bug: v8:7793
TBR: danno@chromium.org
Change-Id: I8ed4bfd04793c8a8805a4a3dd5cf2a85c20ce786
Reviewed-on: https://chromium-review.googlesource.com/1165237
Commit-Queue: Tobias Tebbi <tebbi@chromium.org>
Reviewed-by: 's avatarTobias Tebbi <tebbi@chromium.org>
Cr-Commit-Position: refs/heads/master@{#54948}
parent 78c20334
......@@ -63,7 +63,7 @@ type ExtractFixedArrayFlags generates
type ParameterMode generates 'TNode<Int32T>' constexpr 'ParameterMode';
type RootListIndex generates 'TNode<Int32T>' constexpr 'Heap::RootListIndex';
type MessageTemplate constexpr 'MessageTemplate';
type MessageTemplate constexpr 'MessageTemplate::Template';
type HasPropertyLookupMode constexpr 'HasPropertyLookupMode';
type ToIntegerTruncationMode constexpr 'ToIntegerTruncationMode';
......
......@@ -10,7 +10,7 @@ module typed_array {
extern macro LoadFixedTypedArrayElementAsTagged(
RawPtr, Smi, constexpr ElementsKind, constexpr ParameterMode): Object;
extern macro StoreFixedTypedArrayElementFromTagged(
Context, FixedArrayBase, Smi, Object, constexpr ElementsKind,
Context, FixedTypedArrayBase, Smi, Object, constexpr ElementsKind,
constexpr ParameterMode);
type LoadFn = builtin(Context, JSTypedArray, Smi) => Object;
......
......@@ -1367,11 +1367,6 @@ LocationReference ImplementationVisitor::GetLocationReference(
declarations()->LookupValue((*result.declarable())->name() + "." +
expr->field),
{}, {});
} else {
return LocationReference(
nullptr,
VisitResult(result.type(), result.RValue() + "." + expr->field), {});
}
}
return LocationReference(nullptr, result, {});
......@@ -1422,17 +1417,8 @@ VisitResult ImplementationVisitor::GenerateFetchFromLocation(
if (reference.value != nullptr) {
return GenerateFetchFromLocation(reference);
} else if (const StructType* struct_type = StructType::DynamicCast(type)) {
auto& fields = struct_type->fields();
auto i = std::find_if(
fields.begin(), fields.end(),
[&](const NameAndType& f) { return f.name == expr->field; });
if (i == fields.end()) {
std::stringstream s;
s << "\"" << expr->field << "\" is not a field of struct type \""
<< struct_type->name() << "\"";
ReportError(s.str());
}
return VisitResult(i->type, reference.base.RValue());
return VisitResult(struct_type->GetFieldType(expr->field),
reference.base.RValue() + "." + expr->field);
} else {
Arguments arguments;
arguments.parameters = {reference.base};
......@@ -1488,7 +1474,7 @@ void ImplementationVisitor::GenerateAssignToLocation(
ReportError(s.str());
}
GenerateAssignToVariable(var, assignment_value);
} else if (auto access = FieldAccessExpression::cast(location)) {
} else if (auto access = FieldAccessExpression::DynamicCast(location)) {
GenerateCall(std::string(".") + access->field + "=",
{{reference.base, assignment_value}, {}});
} else {
......
......@@ -19,8 +19,8 @@ namespace internal {
namespace torque {
struct LocationReference {
LocationReference(Value* v, VisitResult b, VisitResult i)
: value(v), base(b), index(i) {}
LocationReference(Value* value, VisitResult base, VisitResult index)
: value(value), base(base), index(index) {}
Value* value;
VisitResult base;
VisitResult index;
......
......@@ -270,6 +270,7 @@ std::string VisitResult::LValue() const {
}
std::string VisitResult::RValue() const {
std::string result;
if (declarable()) {
auto value = *declarable();
if (value->IsVariable() && !Variable::cast(value)->IsDefined()) {
......@@ -277,10 +278,12 @@ std::string VisitResult::RValue() const {
s << "\"" << value->name() << "\" is used before it is defined";
ReportError(s.str());
}
return value->RValue();
result = value->RValue();
} else {
return value_;
result = value_;
}
return "implicit_cast<" + type()->GetGeneratedTypeName() + ">(" + result +
")";
}
} // namespace torque
......
......@@ -311,6 +311,15 @@ class StructType final : public Type {
bool IsConstexpr() const override { return false; }
const std::vector<NameAndType>& fields() const { return fields_; }
const Type* GetFieldType(const std::string& fieldname) const {
for (const NameAndType& field : fields()) {
if (field.name == fieldname) return field.type;
}
std::stringstream s;
s << "\"" << fieldname << "\" is not a field of struct type \"" << name()
<< "\"";
ReportError(s.str());
}
const std::string& name() const { return name_; }
Module* module() const { return module_; }
......
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