[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: Tobias Tebbi <tebbi@chromium.org>
Cr-Commit-Position: refs/heads/master@{#54948}
This commit is contained in:
Tobias Tebbi 2018-08-07 15:41:32 +02:00 committed by Commit Bot
parent 78c20334a4
commit 469522160b
6 changed files with 21 additions and 23 deletions

View File

@ -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';

View File

@ -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;

View File

@ -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 {

View File

@ -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;

View File

@ -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

View File

@ -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_; }