1 // Copyright 2017 the V8 project authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
4
5 #include "src/torque/type-visitor.h"
6
7 #include "src/common/globals.h"
8 #include "src/torque/declarable.h"
9 #include "src/torque/global-context.h"
10 #include "src/torque/kythe-data.h"
11 #include "src/torque/server-data.h"
12 #include "src/torque/type-inference.h"
13 #include "src/torque/type-oracle.h"
14
15 namespace v8 {
16 namespace internal {
17 namespace torque {
18
ComputeType(TypeDeclaration * decl,MaybeSpecializationKey specialized_from,Scope * specialization_requester)19 const Type* TypeVisitor::ComputeType(TypeDeclaration* decl,
20 MaybeSpecializationKey specialized_from,
21 Scope* specialization_requester) {
22 SourcePosition requester_position = CurrentSourcePosition::Get();
23 CurrentSourcePosition::Scope scope(decl->pos);
24 Scope* current_scope = CurrentScope::Get();
25 if (specialized_from) {
26 current_scope = TypeOracle::CreateGenericTypeInstantiationNamespace();
27 current_scope->SetSpecializationRequester(
28 {requester_position, specialization_requester,
29 Type::ComputeName(decl->name->value, specialized_from)});
30 }
31 CurrentScope::Scope new_current_scope_scope(current_scope);
32 if (specialized_from) {
33 auto& params = specialized_from->generic->generic_parameters();
34 auto arg_types_iterator = specialized_from->specialized_types.begin();
35 for (auto param : params) {
36 TypeAlias* alias =
37 Declarations::DeclareType(param.name, *arg_types_iterator);
38 alias->SetIsUserDefined(false);
39 arg_types_iterator++;
40 }
41 }
42
43 switch (decl->kind) {
44 #define ENUM_ITEM(name) \
45 case AstNode::Kind::k##name: \
46 return ComputeType(name::cast(decl), specialized_from);
47 AST_TYPE_DECLARATION_NODE_KIND_LIST(ENUM_ITEM)
48 #undef ENUM_ITEM
49 default:
50 UNIMPLEMENTED();
51 }
52 }
53
ComputeType(TypeAliasDeclaration * decl,MaybeSpecializationKey specialized_from)54 const Type* TypeVisitor::ComputeType(TypeAliasDeclaration* decl,
55 MaybeSpecializationKey specialized_from) {
56 const Type* type = ComputeType(decl->type);
57 type->AddAlias(decl->name->value);
58 return type;
59 }
60
61 namespace {
ComputeGeneratesType(base::Optional<std::string> opt_gen,bool enforce_tnode_type)62 std::string ComputeGeneratesType(base::Optional<std::string> opt_gen,
63 bool enforce_tnode_type) {
64 if (!opt_gen) return "";
65 const std::string& generates = *opt_gen;
66 if (enforce_tnode_type) {
67 return UnwrapTNodeTypeName(generates);
68 }
69 return generates;
70 }
71 } // namespace
72
ComputeType(AbstractTypeDeclaration * decl,MaybeSpecializationKey specialized_from)73 const AbstractType* TypeVisitor::ComputeType(
74 AbstractTypeDeclaration* decl, MaybeSpecializationKey specialized_from) {
75 std::string generates =
76 ComputeGeneratesType(decl->generates, !decl->IsConstexpr());
77
78 const Type* parent_type = nullptr;
79 if (decl->extends) {
80 parent_type = TypeVisitor::ComputeType(*decl->extends);
81 if (parent_type->IsUnionType()) {
82 // UnionType::IsSupertypeOf requires that types can only extend from non-
83 // union types in order to work correctly.
84 ReportError("type \"", decl->name->value,
85 "\" cannot extend a type union");
86 }
87 }
88
89 if (decl->IsConstexpr() && decl->IsTransient()) {
90 ReportError("cannot declare a transient type that is also constexpr");
91 }
92
93 const Type* non_constexpr_version = nullptr;
94 if (decl->IsConstexpr()) {
95 QualifiedName non_constexpr_name{GetNonConstexprName(decl->name->value)};
96 if (auto type = Declarations::TryLookupType(non_constexpr_name)) {
97 non_constexpr_version = *type;
98 }
99 }
100
101 return TypeOracle::GetAbstractType(parent_type, decl->name->value,
102 decl->flags, generates,
103 non_constexpr_version, specialized_from);
104 }
105
DeclareMethods(AggregateType * container_type,const std::vector<Declaration * > & methods)106 void DeclareMethods(AggregateType* container_type,
107 const std::vector<Declaration*>& methods) {
108 for (auto declaration : methods) {
109 CurrentSourcePosition::Scope pos_scope(declaration->pos);
110 TorqueMacroDeclaration* method =
111 TorqueMacroDeclaration::DynamicCast(declaration);
112 Signature signature = TypeVisitor::MakeSignature(method);
113 signature.parameter_names.insert(
114 signature.parameter_names.begin() + signature.implicit_count,
115 MakeNode<Identifier>(kThisParameterName));
116 Statement* body = *(method->body);
117 const std::string& method_name(method->name->value);
118 signature.parameter_types.types.insert(
119 signature.parameter_types.types.begin() + signature.implicit_count,
120 container_type);
121 Method* m = Declarations::CreateMethod(container_type, method_name,
122 signature, body);
123 m->SetPosition(method->pos);
124 m->SetIdentifierPosition(method->name->pos);
125 }
126 }
127
ComputeType(BitFieldStructDeclaration * decl,MaybeSpecializationKey specialized_from)128 const BitFieldStructType* TypeVisitor::ComputeType(
129 BitFieldStructDeclaration* decl, MaybeSpecializationKey specialized_from) {
130 CurrentSourcePosition::Scope position_scope(decl->pos);
131 if (specialized_from.has_value()) {
132 ReportError("Bitfield struct specialization is not supported");
133 }
134 const Type* parent = TypeVisitor::ComputeType(decl->parent);
135 if (!IsAnyUnsignedInteger(parent)) {
136 ReportError(
137 "Bitfield struct must extend from an unsigned integer type, not ",
138 parent->ToString());
139 }
140 auto opt_size = SizeOf(parent);
141 if (!opt_size.has_value()) {
142 ReportError("Cannot determine size of bitfield struct ", decl->name->value,
143 " because of unsized parent type ", parent->ToString());
144 }
145 const size_t size = 8 * std::get<0>(*opt_size); // Convert bytes to bits.
146 BitFieldStructType* type = TypeOracle::GetBitFieldStructType(parent, decl);
147
148 // Iterate through all of the declared fields, checking their validity and
149 // registering them on the newly-constructed BitFieldStructType instance.
150 int offset = 0;
151 for (const auto& field : decl->fields) {
152 CurrentSourcePosition::Scope field_position_scope(
153 field.name_and_type.type->pos);
154 const Type* field_type = TypeVisitor::ComputeType(field.name_and_type.type);
155 if (!IsAllowedAsBitField(field_type)) {
156 ReportError("Type not allowed as bitfield: ",
157 field.name_and_type.name->value);
158 }
159
160 // Compute the maximum number of bits that could be used for a field of this
161 // type. Booleans are a special case, not included in SizeOf, because their
162 // runtime size is 32 bits but they should only occupy 1 bit as a bitfield.
163 size_t field_type_size = 0;
164 if (field_type->IsSubtypeOf(TypeOracle::GetBoolType())) {
165 field_type_size = 1;
166 } else {
167 auto opt_field_type_size = SizeOf(field_type);
168 if (!opt_field_type_size.has_value()) {
169 ReportError("Size unknown for type ", field_type->ToString());
170 }
171 field_type_size = 8 * std::get<0>(*opt_field_type_size);
172 }
173
174 if (field.num_bits < 1 ||
175 static_cast<size_t>(field.num_bits) > field_type_size) {
176 ReportError("Invalid number of bits for ",
177 field.name_and_type.name->value);
178 }
179 type->RegisterField({field.name_and_type.name->pos,
180 {field.name_and_type.name->value, field_type},
181 offset,
182 field.num_bits});
183 offset += field.num_bits;
184 if (static_cast<size_t>(offset) > size) {
185 ReportError("Too many total bits in ", decl->name->value);
186 }
187 }
188
189 return type;
190 }
191
ComputeType(StructDeclaration * decl,MaybeSpecializationKey specialized_from)192 const StructType* TypeVisitor::ComputeType(
193 StructDeclaration* decl, MaybeSpecializationKey specialized_from) {
194 StructType* struct_type = TypeOracle::GetStructType(decl, specialized_from);
195 CurrentScope::Scope struct_namespace_scope(struct_type->nspace());
196 CurrentSourcePosition::Scope decl_position_activator(decl->pos);
197
198 ResidueClass offset = 0;
199 for (auto& field : decl->fields) {
200 CurrentSourcePosition::Scope position_activator(
201 field.name_and_type.type->pos);
202 const Type* field_type = TypeVisitor::ComputeType(field.name_and_type.type);
203 if (field_type->IsConstexpr()) {
204 ReportError("struct field \"", field.name_and_type.name->value,
205 "\" carries constexpr type \"", *field_type, "\"");
206 }
207 Field f{field.name_and_type.name->pos,
208 struct_type,
209 base::nullopt,
210 {field.name_and_type.name->value, field_type},
211 offset.SingleValue(),
212 false,
213 field.const_qualified,
214 FieldSynchronization::kNone,
215 FieldSynchronization::kNone};
216 auto optional_size = SizeOf(f.name_and_type.type);
217 struct_type->RegisterField(f);
218 // Offsets are assigned based on an assumption of no space between members.
219 // This might lead to invalid alignment in some cases, but most structs are
220 // never actually packed in memory together (they just represent a batch of
221 // CSA TNode values that should be passed around together). For any struct
222 // that is used as a class field, we verify its offsets when setting up the
223 // class type.
224 if (optional_size.has_value()) {
225 size_t field_size = 0;
226 std::tie(field_size, std::ignore) = *optional_size;
227 offset += field_size;
228 } else {
229 // Structs may contain fields that aren't representable in packed form. If
230 // so, the offset of subsequent fields are marked as invalid.
231 offset = ResidueClass::Unknown();
232 }
233 }
234 return struct_type;
235 }
236
ComputeType(ClassDeclaration * decl,MaybeSpecializationKey specialized_from)237 const ClassType* TypeVisitor::ComputeType(
238 ClassDeclaration* decl, MaybeSpecializationKey specialized_from) {
239 // TODO(sigurds): Remove this hack by introducing a declarable for classes.
240 const TypeAlias* alias =
241 Declarations::LookupTypeAlias(QualifiedName(decl->name->value));
242 DCHECK_EQ(*alias->delayed_, decl);
243 ClassFlags flags = decl->flags;
244 bool is_shape = flags & ClassFlag::kIsShape;
245 std::string generates = decl->name->value;
246 const Type* super_type = TypeVisitor::ComputeType(decl->super);
247 if (is_shape) {
248 if (!(flags & ClassFlag::kExtern)) {
249 ReportError("Shapes must be extern, add \"extern\" to the declaration.");
250 }
251 if (flags & ClassFlag::kUndefinedLayout) {
252 ReportError("Shapes need to define their layout.");
253 }
254 const ClassType* super_class = ClassType::DynamicCast(super_type);
255 if (!super_class ||
256 !super_class->IsSubtypeOf(TypeOracle::GetJSObjectType())) {
257 Error("Shapes need to extend a subclass of ",
258 *TypeOracle::GetJSObjectType())
259 .Throw();
260 }
261 // Shapes use their super class in CSA code since they have incomplete
262 // support for type-checks on the C++ side.
263 generates = super_class->name();
264 }
265 if (super_type != TypeOracle::GetStrongTaggedType()) {
266 const ClassType* super_class = ClassType::DynamicCast(super_type);
267 if (!super_class) {
268 ReportError(
269 "class \"", decl->name->value,
270 "\" must extend either StrongTagged or an already declared class");
271 }
272 if (super_class->HasUndefinedLayout() &&
273 !(flags & ClassFlag::kUndefinedLayout)) {
274 Error("Class \"", decl->name->value,
275 "\" defines its layout but extends a class which does not")
276 .Position(decl->pos);
277 }
278 if ((flags & ClassFlag::kExport) &&
279 !(super_class->ShouldExport() || super_class->IsExtern())) {
280 Error("cannot export class ", decl->name,
281 " because superclass is neither @export or extern");
282 }
283 }
284 if ((flags & ClassFlag::kGenerateBodyDescriptor ||
285 flags & ClassFlag::kExport) &&
286 flags & ClassFlag::kUndefinedLayout) {
287 Error("Class \"", decl->name->value,
288 "\" requires a layout but doesn't have one");
289 }
290 if (flags & ClassFlag::kGenerateUniqueMap) {
291 if (!(flags & ClassFlag::kExtern)) {
292 Error("No need to specify ", ANNOTATION_GENERATE_UNIQUE_MAP,
293 ", non-extern classes always have a unique map.");
294 }
295 if (flags & ClassFlag::kAbstract) {
296 Error(ANNOTATION_ABSTRACT, " and ", ANNOTATION_GENERATE_UNIQUE_MAP,
297 " shouldn't be used together, because abstract classes are never "
298 "instantiated.");
299 }
300 }
301 if ((flags & ClassFlag::kGenerateFactoryFunction) &&
302 (flags & ClassFlag::kAbstract)) {
303 Error(ANNOTATION_ABSTRACT, " and ", ANNOTATION_GENERATE_FACTORY_FUNCTION,
304 " shouldn't be used together, because abstract classes are never "
305 "instantiated.");
306 }
307 if (flags & ClassFlag::kExtern) {
308 if (decl->generates) {
309 bool enforce_tnode_type = true;
310 std::string explicit_generates =
311 ComputeGeneratesType(decl->generates, enforce_tnode_type);
312 if (explicit_generates == generates) {
313 Lint("Unnecessary 'generates' clause for class ", decl->name->value);
314 }
315 generates = explicit_generates;
316 }
317 if (flags & ClassFlag::kExport) {
318 Error("cannot export a class that is marked extern");
319 }
320 } else {
321 if (decl->generates) {
322 ReportError("Only extern classes can specify a generated type.");
323 }
324 if (super_type != TypeOracle::GetStrongTaggedType()) {
325 if (flags & ClassFlag::kUndefinedLayout) {
326 Error("non-external classes must have defined layouts");
327 }
328 }
329 }
330 if (!(flags & ClassFlag::kExtern) &&
331 (flags & ClassFlag::kHasSameInstanceTypeAsParent)) {
332 Error("non-extern Torque-defined classes must have unique instance types");
333 }
334 if ((flags & ClassFlag::kHasSameInstanceTypeAsParent) &&
335 !(flags & ClassFlag::kDoNotGenerateCast || flags & ClassFlag::kIsShape)) {
336 Error(
337 "classes that inherit their instance type must be annotated with "
338 "@doNotGenerateCast");
339 }
340
341 return TypeOracle::GetClassType(super_type, decl->name->value, flags,
342 generates, decl, alias);
343 }
344
ComputeType(TypeExpression * type_expression)345 const Type* TypeVisitor::ComputeType(TypeExpression* type_expression) {
346 if (auto* basic = BasicTypeExpression::DynamicCast(type_expression)) {
347 QualifiedName qualified_name{basic->namespace_qualification,
348 basic->name->value};
349 auto& args = basic->generic_arguments;
350 const Type* type;
351 SourcePosition pos = SourcePosition::Invalid();
352
353 if (args.empty()) {
354 auto* alias = Declarations::LookupTypeAlias(qualified_name);
355 type = alias->type();
356 pos = alias->GetDeclarationPosition();
357 if (GlobalContext::collect_kythe_data()) {
358 if (alias->IsUserDefined()) {
359 KytheData::AddTypeUse(basic->name->pos, alias);
360 }
361 }
362 } else {
363 auto* generic_type =
364 Declarations::LookupUniqueGenericType(qualified_name);
365 type = TypeOracle::GetGenericTypeInstance(generic_type,
366 ComputeTypeVector(args));
367 pos = generic_type->declaration()->name->pos;
368 if (GlobalContext::collect_kythe_data()) {
369 KytheData::AddTypeUse(basic->name->pos, generic_type);
370 }
371 }
372
373 if (GlobalContext::collect_language_server_data()) {
374 LanguageServerData::AddDefinition(type_expression->pos, pos);
375 }
376 return type;
377
378 } else if (auto* union_type =
379 UnionTypeExpression::DynamicCast(type_expression)) {
380 return TypeOracle::GetUnionType(ComputeType(union_type->a),
381 ComputeType(union_type->b));
382 } else if (auto* function_type_exp =
383 FunctionTypeExpression::DynamicCast(type_expression)) {
384 TypeVector argument_types;
385 for (TypeExpression* type_exp : function_type_exp->parameters) {
386 argument_types.push_back(ComputeType(type_exp));
387 }
388 return TypeOracle::GetBuiltinPointerType(
389 argument_types, ComputeType(function_type_exp->return_type));
390 } else {
391 auto* precomputed = PrecomputedTypeExpression::cast(type_expression);
392 return precomputed->type;
393 }
394 }
395
MakeSignature(const CallableDeclaration * declaration)396 Signature TypeVisitor::MakeSignature(const CallableDeclaration* declaration) {
397 LabelDeclarationVector definition_vector;
398 for (const auto& label : declaration->labels) {
399 LabelDeclaration def = {label.name, ComputeTypeVector(label.types)};
400 definition_vector.push_back(def);
401 }
402 base::Optional<std::string> arguments_variable;
403 if (declaration->parameters.has_varargs)
404 arguments_variable = declaration->parameters.arguments_variable;
405 Signature result{declaration->parameters.names,
406 arguments_variable,
407 {ComputeTypeVector(declaration->parameters.types),
408 declaration->parameters.has_varargs},
409 declaration->parameters.implicit_count,
410 ComputeType(declaration->return_type),
411 definition_vector,
412 declaration->transitioning};
413 return result;
414 }
415
VisitClassFieldsAndMethods(ClassType * class_type,const ClassDeclaration * class_declaration)416 void TypeVisitor::VisitClassFieldsAndMethods(
417 ClassType* class_type, const ClassDeclaration* class_declaration) {
418 const ClassType* super_class = class_type->GetSuperClass();
419 ResidueClass class_offset = 0;
420 size_t header_size = 0;
421 if (super_class) {
422 class_offset = super_class->size();
423 header_size = super_class->header_size();
424 }
425
426 for (const ClassFieldExpression& field_expression :
427 class_declaration->fields) {
428 CurrentSourcePosition::Scope position_activator(
429 field_expression.name_and_type.type->pos);
430 const Type* field_type = ComputeType(field_expression.name_and_type.type);
431 if (class_type->IsShape()) {
432 if (!field_type->IsSubtypeOf(TypeOracle::GetObjectType())) {
433 ReportError(
434 "in-object properties only support subtypes of Object, but "
435 "found type ",
436 *field_type);
437 }
438 if (field_expression.custom_weak_marking) {
439 ReportError("in-object properties cannot use @customWeakMarking");
440 }
441 }
442 base::Optional<ClassFieldIndexInfo> array_length = field_expression.index;
443 const Field& field = class_type->RegisterField(
444 {field_expression.name_and_type.name->pos,
445 class_type,
446 array_length,
447 {field_expression.name_and_type.name->value, field_type},
448 class_offset.SingleValue(),
449 field_expression.custom_weak_marking,
450 field_expression.const_qualified,
451 field_expression.read_synchronization,
452 field_expression.write_synchronization});
453 ResidueClass field_size = std::get<0>(field.GetFieldSizeInformation());
454 if (field.index) {
455 // Validate that a value at any index in a packed array is aligned
456 // correctly, since it is possible to define a struct whose size is not a
457 // multiple of its alignment.
458 field.ValidateAlignment(class_offset +
459 field_size * ResidueClass::Unknown());
460
461 if (auto literal =
462 IntegerLiteralExpression::DynamicCast(field.index->expr)) {
463 if (auto value = literal->value.TryTo<size_t>()) {
464 field_size *= *value;
465 } else {
466 Error("Not a valid field index").Position(field.pos);
467 }
468 } else {
469 field_size *= ResidueClass::Unknown();
470 }
471 }
472 field.ValidateAlignment(class_offset);
473 class_offset += field_size;
474 // In-object properties are not considered part of the header.
475 if (class_offset.SingleValue() && !class_type->IsShape()) {
476 header_size = *class_offset.SingleValue();
477 }
478 if (!field.index && !class_offset.SingleValue()) {
479 Error("Indexed fields have to be at the end of the object")
480 .Position(field.pos);
481 }
482 }
483 DCHECK_GT(header_size, 0);
484 class_type->header_size_ = header_size;
485 class_type->size_ = class_offset;
486 class_type->GenerateAccessors();
487 DeclareMethods(class_type, class_declaration->methods);
488 }
489
VisitStructMethods(StructType * struct_type,const StructDeclaration * struct_declaration)490 void TypeVisitor::VisitStructMethods(
491 StructType* struct_type, const StructDeclaration* struct_declaration) {
492 DeclareMethods(struct_type, struct_declaration->methods);
493 }
494
ComputeTypeForStructExpression(TypeExpression * type_expression,const std::vector<const Type * > & term_argument_types)495 const Type* TypeVisitor::ComputeTypeForStructExpression(
496 TypeExpression* type_expression,
497 const std::vector<const Type*>& term_argument_types) {
498 auto* basic = BasicTypeExpression::DynamicCast(type_expression);
499 if (!basic) {
500 ReportError("expected basic type expression referring to struct");
501 }
502
503 QualifiedName qualified_name{basic->namespace_qualification,
504 basic->name->value};
505 base::Optional<GenericType*> maybe_generic_type =
506 Declarations::TryLookupGenericType(qualified_name);
507
508 StructDeclaration* decl =
509 maybe_generic_type
510 ? StructDeclaration::DynamicCast((*maybe_generic_type)->declaration())
511 : nullptr;
512
513 // Compute types of non-generic structs as usual
514 if (!(maybe_generic_type && decl)) {
515 const Type* type = ComputeType(type_expression);
516 if (!type->IsStructType() && !type->IsBitFieldStructType()) {
517 ReportError(*type,
518 " is not a struct or bitfield struct, but used like one");
519 }
520 return type;
521 }
522
523 auto generic_type = *maybe_generic_type;
524 auto explicit_type_arguments = ComputeTypeVector(basic->generic_arguments);
525
526 std::vector<TypeExpression*> term_parameters;
527 auto& fields = decl->fields;
528 term_parameters.reserve(fields.size());
529 for (auto& field : fields) {
530 term_parameters.push_back(field.name_and_type.type);
531 }
532
533 CurrentScope::Scope generic_scope(generic_type->ParentScope());
534 TypeArgumentInference inference(
535 generic_type->generic_parameters(), explicit_type_arguments,
536 term_parameters,
537 TransformVector<base::Optional<const Type*>>(term_argument_types));
538
539 if (inference.HasFailed()) {
540 ReportError("failed to infer type arguments for struct ", basic->name,
541 " initialization: ", inference.GetFailureReason());
542 }
543 if (GlobalContext::collect_language_server_data()) {
544 LanguageServerData::AddDefinition(type_expression->pos,
545 generic_type->declaration()->name->pos);
546 }
547 return StructType::cast(
548 TypeOracle::GetGenericTypeInstance(generic_type, inference.GetResult()));
549 }
550
551 } // namespace torque
552 } // namespace internal
553 } // namespace v8
554