Line data Source code
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/declaration-visitor.h"
6 : #include "src/torque/ast.h"
7 :
8 : namespace v8 {
9 : namespace internal {
10 : namespace torque {
11 :
12 1176 : void DeclarationVisitor::Visit(Declaration* decl) {
13 1176 : CurrentSourcePosition::Scope scope(decl->pos);
14 1176 : switch (decl->kind) {
15 : #define ENUM_ITEM(name) \
16 : case AstNode::Kind::k##name: \
17 : return Visit(name::cast(decl));
18 1126 : AST_DECLARATION_NODE_KIND_LIST(ENUM_ITEM)
19 : #undef ENUM_ITEM
20 : default:
21 0 : UNIMPLEMENTED();
22 : }
23 : }
24 :
25 705 : void DeclarationVisitor::Visit(CallableNode* decl, const Signature& signature,
26 : base::Optional<Statement*> body) {
27 705 : switch (decl->kind) {
28 : #define ENUM_ITEM(name) \
29 : case AstNode::Kind::k##name: \
30 : return Visit(name::cast(decl), signature, body);
31 705 : AST_CALLABLE_NODE_KIND_LIST(ENUM_ITEM)
32 : #undef ENUM_ITEM
33 : default:
34 0 : UNIMPLEMENTED();
35 : }
36 : }
37 :
38 150 : Builtin* DeclarationVisitor::CreateBuiltin(BuiltinDeclaration* decl,
39 : std::string external_name,
40 : std::string readable_name,
41 : Signature signature,
42 : base::Optional<Statement*> body) {
43 150 : const bool javascript = decl->javascript_linkage;
44 150 : const bool varargs = decl->signature->parameters.has_varargs;
45 : Builtin::Kind kind = !javascript ? Builtin::kStub
46 : : varargs ? Builtin::kVarArgsJavaScript
47 150 : : Builtin::kFixedArgsJavaScript;
48 :
49 600 : if (signature.types().size() == 0 ||
50 : !(signature.types()[0] ==
51 600 : Declarations::LookupGlobalType(CONTEXT_TYPE_STRING))) {
52 0 : std::stringstream stream;
53 0 : stream << "first parameter to builtin " << decl->name
54 0 : << " is not a context but should be";
55 0 : ReportError(stream.str());
56 : }
57 :
58 150 : if (varargs && !javascript) {
59 0 : std::stringstream stream;
60 0 : stream << "builtin " << decl->name
61 0 : << " with rest parameters must be a JavaScript builtin";
62 0 : ReportError(stream.str());
63 : }
64 :
65 150 : if (javascript) {
66 232 : if (signature.types().size() < 2 ||
67 : !(signature.types()[1] ==
68 232 : Declarations::LookupGlobalType(OBJECT_TYPE_STRING))) {
69 0 : std::stringstream stream;
70 0 : stream << "second parameter to javascript builtin " << decl->name
71 0 : << " is " << *signature.types()[1] << " but should be Object";
72 0 : ReportError(stream.str());
73 : }
74 : }
75 :
76 1328 : for (size_t i = 0; i < signature.types().size(); ++i) {
77 514 : if (const StructType* type =
78 514 : StructType::DynamicCast(signature.types()[i])) {
79 0 : std::stringstream stream;
80 0 : stream << "builtin '" << decl->name << "' uses the struct '"
81 0 : << type->name() << "' as argument '"
82 0 : << signature.parameter_names[i] << "'. This is not supported.";
83 0 : ReportError(stream.str());
84 : }
85 : }
86 :
87 150 : if (const StructType* struct_type =
88 150 : StructType::DynamicCast(signature.return_type)) {
89 0 : std::stringstream stream;
90 0 : stream << "builtins (in this case " << decl->name
91 0 : << ") cannot return structs (in this case " << struct_type->name()
92 0 : << ")";
93 0 : ReportError(stream.str());
94 : }
95 :
96 : return Declarations::CreateBuiltin(
97 : std::move(external_name), std::move(readable_name), kind,
98 600 : std::move(signature), decl->transitioning, body);
99 : }
100 :
101 14 : void DeclarationVisitor::Visit(ExternalRuntimeDeclaration* decl,
102 : const Signature& signature,
103 : base::Optional<Statement*> body) {
104 14 : if (GlobalContext::verbose()) {
105 0 : std::cout << "found declaration of external runtime " << decl->name
106 0 : << " with signature ";
107 : }
108 :
109 56 : if (signature.parameter_types.types.size() == 0 ||
110 : !(signature.parameter_types.types[0] ==
111 56 : Declarations::LookupGlobalType(CONTEXT_TYPE_STRING))) {
112 0 : std::stringstream stream;
113 0 : stream << "first parameter to runtime " << decl->name
114 0 : << " is not a context but should be";
115 0 : ReportError(stream.str());
116 : }
117 :
118 28 : if (signature.return_type->IsStructType()) {
119 0 : std::stringstream stream;
120 0 : stream << "runtime functions (in this case" << decl->name
121 0 : << ") cannot return structs (in this case "
122 0 : << static_cast<const StructType*>(signature.return_type)->name()
123 0 : << ")";
124 0 : ReportError(stream.str());
125 : }
126 :
127 : Declarations::DeclareRuntimeFunction(decl->name, signature,
128 14 : decl->transitioning);
129 14 : }
130 :
131 393 : void DeclarationVisitor::Visit(ExternalMacroDeclaration* decl,
132 : const Signature& signature,
133 : base::Optional<Statement*> body) {
134 393 : if (GlobalContext::verbose()) {
135 0 : std::cout << "found declaration of external macro " << decl->name
136 0 : << " with signature ";
137 : }
138 :
139 : Declarations::DeclareMacro(decl->name, decl->external_assembler_name,
140 1572 : signature, decl->transitioning, body, decl->op);
141 393 : }
142 :
143 78 : void DeclarationVisitor::Visit(TorqueBuiltinDeclaration* decl,
144 : const Signature& signature,
145 : base::Optional<Statement*> body) {
146 : Declarations::Declare(
147 234 : decl->name, CreateBuiltin(decl, decl->name, decl->name, signature, body));
148 78 : }
149 :
150 202 : void DeclarationVisitor::Visit(TorqueMacroDeclaration* decl,
151 : const Signature& signature,
152 : base::Optional<Statement*> body) {
153 : Declarations::DeclareMacro(decl->name, base::nullopt, signature,
154 808 : decl->transitioning, body, decl->op);
155 202 : }
156 :
157 0 : void DeclarationVisitor::Visit(IntrinsicDeclaration* decl,
158 : const Signature& signature,
159 : base::Optional<Statement*> body) {
160 0 : Declarations::DeclareIntrinsic(decl->name, signature);
161 0 : }
162 :
163 24 : void DeclarationVisitor::Visit(ConstDeclaration* decl) {
164 : Declarations::DeclareNamespaceConstant(
165 24 : decl->name, Declarations::GetType(decl->type), decl->expression);
166 24 : }
167 :
168 705 : void DeclarationVisitor::Visit(StandardDeclaration* decl) {
169 1410 : Signature signature = MakeSignature(decl->callable->signature.get());
170 705 : Visit(decl->callable, signature, decl->body);
171 705 : }
172 :
173 0 : void DeclarationVisitor::Visit(GenericDeclaration* decl) {
174 50 : Declarations::DeclareGeneric(decl->callable->name, decl);
175 0 : }
176 :
177 138 : void DeclarationVisitor::Visit(SpecializationDeclaration* decl) {
178 138 : if ((decl->body != nullptr) == decl->external) {
179 0 : std::stringstream stream;
180 0 : stream << "specialization of " << decl->name
181 0 : << " must either be marked 'extern' or have a body";
182 0 : ReportError(stream.str());
183 : }
184 :
185 138 : std::vector<Generic*> generic_list = Declarations::LookupGeneric(decl->name);
186 : // Find the matching generic specialization based on the concrete parameter
187 : // list.
188 138 : Generic* matching_generic = nullptr;
189 276 : Signature signature_with_types = MakeSignature(decl->signature.get());
190 445 : for (Generic* generic : generic_list) {
191 : Signature generic_signature_with_types = MakeSpecializedSignature(
192 338 : SpecializationKey{generic, GetTypeVector(decl->generic_parameters)});
193 169 : if (signature_with_types.HasSameTypesAs(generic_signature_with_types,
194 : ParameterMode::kIgnoreImplicit)) {
195 138 : if (matching_generic != nullptr) {
196 0 : std::stringstream stream;
197 0 : stream << "specialization of " << decl->name
198 0 : << " is ambigous, it matches more than one generic declaration ("
199 0 : << *matching_generic << " and " << *generic << ")";
200 0 : ReportError(stream.str());
201 : }
202 : matching_generic = generic;
203 : }
204 169 : }
205 :
206 138 : if (matching_generic == nullptr) {
207 0 : std::stringstream stream;
208 0 : if (generic_list.size() == 0) {
209 0 : stream << "no generic defined with the name " << decl->name;
210 0 : ReportError(stream.str());
211 : }
212 0 : stream << "specialization of " << decl->name
213 0 : << " doesn't match any generic declaration\n";
214 0 : stream << "specialization signature:";
215 0 : stream << "\n " << signature_with_types;
216 0 : stream << "\ncandidates are:";
217 0 : for (Generic* generic : generic_list) {
218 0 : stream << "\n "
219 : << MakeSpecializedSignature(SpecializationKey{
220 0 : generic, GetTypeVector(decl->generic_parameters)});
221 : }
222 0 : ReportError(stream.str());
223 : }
224 :
225 : Specialize(SpecializationKey{matching_generic,
226 : GetTypeVector(decl->generic_parameters)},
227 : matching_generic->declaration()->callable, decl->signature.get(),
228 276 : decl->body);
229 138 : }
230 :
231 81 : void DeclarationVisitor::Visit(ExternConstDeclaration* decl) {
232 81 : const Type* type = Declarations::GetType(decl->type);
233 81 : if (!type->IsConstexpr()) {
234 0 : std::stringstream stream;
235 0 : stream << "extern constants must have constexpr type, but found: \""
236 0 : << *type << "\"\n";
237 0 : ReportError(stream.str());
238 : }
239 :
240 162 : Declarations::DeclareExternConstant(decl->name, type, decl->literal);
241 81 : }
242 :
243 32 : void DeclarationVisitor::DeclareMethods(
244 : AggregateType* container_type, const std::vector<Declaration*>& methods) {
245 : // Declare the class' methods
246 : IdentifierExpression* constructor_this = MakeNode<IdentifierExpression>(
247 32 : std::vector<std::string>{}, kThisParameterName);
248 : AggregateType* constructor_this_type =
249 : container_type->IsStructType()
250 : ? container_type
251 32 : : ClassType::cast(container_type)->struct_type();
252 87 : for (auto declaration : methods) {
253 23 : CurrentSourcePosition::Scope pos_scope(declaration->pos);
254 : StandardDeclaration* standard_declaration =
255 : StandardDeclaration::DynamicCast(declaration);
256 : DCHECK(standard_declaration);
257 : TorqueMacroDeclaration* method =
258 23 : TorqueMacroDeclaration::DynamicCast(standard_declaration->callable);
259 46 : Signature signature = MakeSignature(method->signature.get());
260 : signature.parameter_names.insert(
261 : signature.parameter_names.begin() + signature.implicit_count,
262 46 : kThisParameterName);
263 23 : Statement* body = *(standard_declaration->body);
264 23 : std::string method_name(method->name);
265 23 : if (method->name == kConstructMethodName) {
266 : signature.parameter_types.types.insert(
267 : signature.parameter_types.types.begin() + signature.implicit_count,
268 20 : constructor_this_type);
269 : // Constructor
270 10 : if (!signature.return_type->IsVoid()) {
271 0 : ReportError("constructors musn't have a return type");
272 : }
273 20 : if (signature.labels.size() != 0) {
274 0 : ReportError("constructors musn't have labels");
275 : }
276 : method_name = kConstructMethodName;
277 : Declarations::CreateMethod(constructor_this_type, method_name, signature,
278 10 : false, body);
279 : } else {
280 : signature.parameter_types.types.insert(
281 : signature.parameter_types.types.begin() + signature.implicit_count,
282 26 : container_type);
283 : Declarations::CreateMethod(container_type, method_name, signature, false,
284 13 : body);
285 : }
286 : }
287 :
288 75 : if (constructor_this_type->Constructors().size() != 0) return;
289 :
290 : // TODO(danno): Currently, default constructors for classes with
291 : // open-ended arrays at the end are not supported. For now, if one is
292 : // encountered, don't actually create the constructor.
293 24 : if (container_type->HasIndexedField()) return;
294 :
295 : // Generate default constructor.
296 : Signature constructor_signature;
297 21 : constructor_signature.parameter_types.var_args = false;
298 21 : constructor_signature.return_type = TypeOracle::GetVoidType();
299 21 : std::vector<const AggregateType*> hierarchy = container_type->GetHierarchy();
300 :
301 : std::vector<Statement*> statements;
302 : std::vector<Statement*> initializer_statements;
303 :
304 : size_t parameter_number = 0;
305 42 : constructor_signature.parameter_names.push_back(kThisParameterName);
306 42 : constructor_signature.parameter_types.types.push_back(constructor_this_type);
307 : std::vector<Expression*> super_arguments;
308 90 : for (auto current_type : hierarchy) {
309 195 : for (auto& f : current_type->fields()) {
310 : DCHECK(!f.index);
311 198 : std::string parameter_name("p" + std::to_string(parameter_number++));
312 99 : constructor_signature.parameter_names.push_back(parameter_name);
313 : constructor_signature.parameter_types.types.push_back(
314 99 : f.name_and_type.type);
315 : IdentifierExpression* value = MakeNode<IdentifierExpression>(
316 297 : std::vector<std::string>{}, parameter_name);
317 99 : if (container_type != current_type) {
318 : super_arguments.push_back(MakeNode<IdentifierExpression>(
319 152 : std::vector<std::string>{}, parameter_name));
320 : } else {
321 : LocationExpression* location = MakeNode<FieldAccessExpression>(
322 122 : constructor_this, f.name_and_type.name);
323 : Statement* statement = MakeNode<ExpressionStatement>(
324 61 : MakeNode<AssignmentExpression>(location, base::nullopt, value));
325 61 : initializer_statements.push_back(statement);
326 : }
327 : }
328 : }
329 :
330 42 : if (hierarchy.size() > 1) {
331 : IdentifierExpression* super_identifier = MakeNode<IdentifierExpression>(
332 11 : std::vector<std::string>{}, kSuperMethodName);
333 : Statement* statement =
334 : MakeNode<ExpressionStatement>(MakeNode<CallMethodExpression>(
335 : constructor_this, super_identifier, super_arguments,
336 22 : std::vector<std::string>{}));
337 11 : statements.push_back(statement);
338 : }
339 :
340 103 : for (auto s : initializer_statements) {
341 61 : statements.push_back(s);
342 : }
343 :
344 42 : Statement* constructor_body = MakeNode<BlockStatement>(false, statements);
345 :
346 : Declarations::CreateMethod(constructor_this_type, kConstructMethodName,
347 63 : constructor_signature, false, constructor_body);
348 : }
349 :
350 13 : void DeclarationVisitor::Visit(StructDeclaration* decl) {
351 13 : StructType* struct_type = Declarations::DeclareStruct(decl->name);
352 : struct_declarations_.push_back(
353 26 : std::make_tuple(CurrentScope::Get(), decl, struct_type));
354 13 : }
355 :
356 19 : void DeclarationVisitor::Visit(ClassDeclaration* decl) {
357 : ClassType* new_class;
358 19 : if (decl->is_extern) {
359 19 : if (!decl->super) {
360 0 : ReportError("Extern class must extend another type.");
361 : }
362 : // Compute the offset of the class' first member. If the class extends
363 : // another class, it's the size of the extended class, otherwise zero.
364 34 : const Type* super_type = Declarations::LookupType(*decl->super);
365 17 : if (super_type != TypeOracle::GetTaggedType()) {
366 : const ClassType* super_class = ClassType::DynamicCast(super_type);
367 16 : if (!super_class) {
368 : ReportError(
369 : "class \"", decl->name,
370 0 : "\" must extend either Tagged or an already declared class");
371 : }
372 : }
373 :
374 : // The generates clause must create a TNode<>
375 17 : std::string generates = decl->name;
376 19 : if (decl->generates) {
377 1 : generates = *decl->generates;
378 5 : if (generates.length() < 7 || generates.substr(0, 6) != "TNode<" ||
379 3 : generates.substr(generates.length() - 1, 1) != ">") {
380 : ReportError("generated type \"", generates,
381 0 : "\" should be of the form \"TNode<...>\"");
382 : }
383 2 : generates = generates.substr(6, generates.length() - 7);
384 : }
385 :
386 : new_class = Declarations::DeclareClass(
387 17 : super_type, decl->name, decl->is_extern, decl->transient, generates);
388 : } else {
389 2 : if (decl->super) {
390 0 : ReportError("Only extern classes can inherit.");
391 : }
392 2 : if (decl->generates) {
393 0 : ReportError("Only extern classes can specify a generated type.");
394 : }
395 : new_class = Declarations::DeclareClass(TypeOracle::GetTaggedType(),
396 : decl->name, decl->is_extern,
397 4 : decl->transient, "FixedArray");
398 : }
399 19 : GlobalContext::RegisterClass(decl->name, new_class);
400 : class_declarations_.push_back(
401 38 : std::make_tuple(CurrentScope::Get(), decl, new_class));
402 19 : }
403 :
404 15 : void DeclarationVisitor::Visit(CppIncludeDeclaration* decl) {
405 30 : GlobalContext::AddCppInclude(decl->include_path);
406 15 : }
407 :
408 87 : void DeclarationVisitor::Visit(TypeDeclaration* decl) {
409 87 : std::string generates = decl->generates ? *decl->generates : std::string("");
410 87 : if (decl->generates) {
411 295 : if (generates.length() < 7 || generates.substr(0, 6) != "TNode<" ||
412 177 : generates.substr(generates.length() - 1, 1) != ">") {
413 : ReportError("generated type \"", generates,
414 0 : "\" should be of the form \"TNode<...>\"");
415 : }
416 118 : generates = generates.substr(6, generates.length() - 7);
417 : }
418 :
419 : const AbstractType* type = Declarations::DeclareAbstractType(
420 210 : decl->name, decl->transient, generates, {}, decl->extends);
421 :
422 87 : if (decl->constexpr_generates) {
423 36 : if (decl->transient) {
424 0 : ReportError("cannot declare a transient type that is also constexpr");
425 : }
426 36 : std::string constexpr_name = CONSTEXPR_TYPE_PREFIX + decl->name;
427 36 : base::Optional<std::string> constexpr_extends;
428 36 : if (decl->extends)
429 26 : constexpr_extends = CONSTEXPR_TYPE_PREFIX + *decl->extends;
430 : Declarations::DeclareAbstractType(constexpr_name, false,
431 36 : *decl->constexpr_generates, type,
432 36 : constexpr_extends);
433 : }
434 87 : }
435 :
436 2903 : void DeclarationVisitor::DeclareSpecializedTypes(const SpecializationKey& key) {
437 : size_t i = 0;
438 : const std::size_t generic_parameter_count =
439 7544 : key.generic->declaration()->generic_parameters.size();
440 5806 : if (generic_parameter_count != key.specialized_types.size()) {
441 0 : std::stringstream stream;
442 0 : stream << "Wrong generic argument count for specialization of \""
443 0 : << key.generic->name() << "\", expected: " << generic_parameter_count
444 0 : << ", actual: " << key.specialized_types.size();
445 0 : ReportError(stream.str());
446 : }
447 :
448 12185 : for (auto type : key.specialized_types) {
449 : std::string generic_type_name =
450 13923 : key.generic->declaration()->generic_parameters[i++];
451 4641 : Declarations::DeclareType(generic_type_name, type, true);
452 : }
453 2903 : }
454 :
455 2715 : Signature DeclarationVisitor::MakeSpecializedSignature(
456 : const SpecializationKey& key) {
457 5430 : CurrentScope::Scope generic_scope(key.generic->ParentScope());
458 : // Create a temporary fake-namespace just to temporarily declare the
459 : // specialization aliases for the generic types to create a signature.
460 8145 : Namespace tmp_namespace("_tmp");
461 2715 : CurrentScope::Scope tmp_namespace_scope(&tmp_namespace);
462 2715 : DeclareSpecializedTypes(key);
463 10860 : return MakeSignature(key.generic->declaration()->callable->signature.get());
464 : }
465 :
466 188 : Callable* DeclarationVisitor::SpecializeImplicit(const SpecializationKey& key) {
467 442 : if (!key.generic->declaration()->body &&
468 66 : IntrinsicDeclaration::DynamicCast(key.generic->declaration()->callable) ==
469 : nullptr) {
470 0 : ReportError("missing specialization of ", key.generic->name(),
471 : " with types <", key.specialized_types, "> declared at ",
472 0 : key.generic->pos());
473 : }
474 188 : CurrentScope::Scope generic_scope(key.generic->ParentScope());
475 : Callable* result =
476 : Specialize(key, key.generic->declaration()->callable, base::nullopt,
477 376 : key.generic->declaration()->body);
478 188 : CurrentScope::Scope callable_scope(result);
479 188 : DeclareSpecializedTypes(key);
480 376 : return result;
481 : }
482 :
483 326 : Callable* DeclarationVisitor::Specialize(
484 : const SpecializationKey& key, CallableNode* declaration,
485 326 : base::Optional<const CallableNodeSignature*> signature,
486 : base::Optional<Statement*> body) {
487 : // TODO(tebbi): The error should point to the source position where the
488 : // instantiation was requested.
489 652 : CurrentSourcePosition::Scope pos_scope(key.generic->declaration()->pos);
490 : size_t generic_parameter_count =
491 652 : key.generic->declaration()->generic_parameters.size();
492 652 : if (generic_parameter_count != key.specialized_types.size()) {
493 0 : std::stringstream stream;
494 0 : stream << "number of template parameters ("
495 0 : << std::to_string(key.specialized_types.size())
496 0 : << ") to intantiation of generic " << declaration->name
497 0 : << " doesnt match the generic's declaration ("
498 0 : << std::to_string(generic_parameter_count) << ")";
499 0 : ReportError(stream.str());
500 : }
501 326 : if (key.generic->GetSpecialization(key.specialized_types)) {
502 0 : ReportError("cannot redeclare specialization of ", key.generic->name(),
503 0 : " with types <", key.specialized_types, ">");
504 : }
505 :
506 : Signature type_signature =
507 652 : signature ? MakeSignature(*signature) : MakeSpecializedSignature(key);
508 :
509 : std::string generated_name = Declarations::GetGeneratedCallableName(
510 326 : declaration->name, key.specialized_types);
511 652 : std::stringstream readable_name;
512 326 : readable_name << declaration->name << "<";
513 : bool first = true;
514 1118 : for (const Type* t : key.specialized_types) {
515 466 : if (!first) readable_name << ", ";
516 466 : readable_name << *t;
517 : first = false;
518 : }
519 326 : readable_name << ">";
520 : Callable* callable;
521 326 : if (MacroDeclaration::DynamicCast(declaration) != nullptr) {
522 : callable = Declarations::CreateMacro(generated_name, readable_name.str(),
523 : base::nullopt, type_signature,
524 1030 : declaration->transitioning, *body);
525 120 : } else if (IntrinsicDeclaration::DynamicCast(declaration) != nullptr) {
526 66 : callable = Declarations::CreateIntrinsic(declaration->name, type_signature);
527 : } else {
528 : BuiltinDeclaration* builtin = BuiltinDeclaration::cast(declaration);
529 : callable = CreateBuiltin(builtin, generated_name, readable_name.str(),
530 216 : type_signature, *body);
531 : }
532 326 : key.generic->AddSpecialization(key.specialized_types, callable);
533 326 : return callable;
534 : }
535 :
536 13 : void DeclarationVisitor::FinalizeStructFieldsAndMethods(
537 : StructType* struct_type, StructDeclaration* struct_declaration) {
538 : size_t offset = 0;
539 63 : for (auto& field : struct_declaration->fields) {
540 37 : const Type* field_type = Declarations::GetType(field.name_and_type.type);
541 : struct_type->RegisterField({field.name_and_type.type->pos,
542 : struct_type,
543 : base::nullopt,
544 : {field.name_and_type.name, field_type},
545 : offset,
546 111 : false});
547 37 : offset += LoweredSlotCount(field_type);
548 : }
549 13 : CurrentSourcePosition::Scope position_activator(struct_declaration->pos);
550 13 : DeclareMethods(struct_type, struct_declaration->methods);
551 13 : }
552 :
553 19 : void DeclarationVisitor::FinalizeClassFieldsAndMethods(
554 : ClassType* class_type, ClassDeclaration* class_declaration) {
555 32 : const ClassType* super_class = class_type->GetSuperClass();
556 38 : size_t class_offset = super_class ? super_class->size() : 0;
557 : bool seen_indexed_field = false;
558 98 : for (ClassFieldExpression& field_expression : class_declaration->fields) {
559 : CurrentSourcePosition::Scope position_activator(
560 60 : field_expression.name_and_type.type->pos);
561 : const Type* field_type =
562 60 : Declarations::GetType(field_expression.name_and_type.type);
563 60 : if (!class_declaration->is_extern) {
564 17 : if (!field_type->IsSubtypeOf(TypeOracle::GetTaggedType())) {
565 0 : ReportError("non-extern classes do not support untagged fields");
566 : }
567 17 : if (field_expression.weak) {
568 0 : ReportError("non-extern classes do not support weak fields");
569 : }
570 : }
571 60 : if (field_expression.index) {
572 4 : if (seen_indexed_field ||
573 2 : (super_class && super_class->HasIndexedField())) {
574 : ReportError(
575 0 : "only one indexable field is currently supported per class");
576 : }
577 : seen_indexed_field = true;
578 : const Field* index_field =
579 2 : &(class_type->LookupField(*field_expression.index));
580 : class_type->RegisterField(
581 : {field_expression.name_and_type.type->pos,
582 : class_type,
583 : index_field,
584 : {field_expression.name_and_type.name, field_type},
585 : class_offset,
586 6 : field_expression.weak});
587 : } else {
588 58 : if (seen_indexed_field) {
589 : ReportError("cannot declare non-indexable field \"",
590 : field_expression.name_and_type.name,
591 : "\" after an indexable field "
592 0 : "declaration");
593 : }
594 : const Field& field = class_type->RegisterField(
595 : {field_expression.name_and_type.type->pos,
596 : class_type,
597 : base::nullopt,
598 : {field_expression.name_and_type.name, field_type},
599 : class_offset,
600 174 : field_expression.weak});
601 : size_t field_size;
602 : std::string size_string;
603 : std::string machine_type;
604 174 : std::tie(field_size, size_string, machine_type) =
605 : field.GetFieldSizeInformation();
606 58 : size_t aligned_offset = class_offset & ~(field_size - 1);
607 58 : if (class_offset != aligned_offset) {
608 : ReportError("field ", field_expression.name_and_type.name,
609 : " is not aligned to its size (", aligned_offset, " vs ",
610 0 : class_offset, " for field size ", field_size, ")");
611 : }
612 58 : class_offset += field_size;
613 : }
614 : }
615 19 : class_type->SetSize(class_offset);
616 :
617 : StructType* this_struct_type = Declarations::DeclareStruct(
618 38 : kClassConstructorThisStructPrefix + class_type->name());
619 : size_t struct_offset = 0;
620 : const StructType* super_struct_type = nullptr;
621 : // In order to ensure "atomicity" of object allocation, a class'
622 : // constructors operate on a per-class internal struct rather than the class
623 : // directly until the constructor has successfully completed and all class
624 : // members are available. Create the appropriate struct type for use in the
625 : // class' constructors, including a '_super' field in the struct that
626 : // contains the values constructed by calls to super constructors.
627 19 : if (super_class) {
628 : super_struct_type = super_class->struct_type();
629 : this_struct_type->RegisterField(
630 : {CurrentSourcePosition::Get(),
631 : super_struct_type,
632 : base::nullopt,
633 : {kConstructorStructSuperFieldName, super_struct_type},
634 : struct_offset,
635 64 : false});
636 16 : struct_offset += LoweredSlotCount(super_struct_type);
637 : }
638 98 : for (auto& field : class_type->fields()) {
639 60 : if (field.index) continue;
640 58 : const Type* field_type = field.name_and_type.type;
641 : this_struct_type->RegisterField({field.pos,
642 : class_type,
643 : base::nullopt,
644 : {field.name_and_type.name, field_type},
645 : struct_offset,
646 174 : false});
647 58 : struct_offset += LoweredSlotCount(field_type);
648 : }
649 : this_struct_type->SetDerivedFrom(class_type);
650 : class_type->SetThisStruct(this_struct_type);
651 :
652 : // For each field, construct AST snippits that implement a CSA accessor
653 : // function and define a corresponding '.field' operator. The
654 : // implementation iterator will turn the snippits into code.
655 98 : for (auto& field : class_type->fields()) {
656 62 : if (field.index) continue;
657 58 : CurrentSourcePosition::Scope position_activator(field.pos);
658 : IdentifierExpression* parameter =
659 116 : MakeNode<IdentifierExpression>(std::string{"o"});
660 :
661 : // Load accessor
662 58 : std::string camel_field_name = CamelifyString(field.name_and_type.name);
663 : std::string load_macro_name =
664 116 : "Load" + class_type->name() + camel_field_name;
665 58 : std::string load_operator_name = "." + field.name_and_type.name;
666 58 : Signature load_signature;
667 116 : load_signature.parameter_names.push_back("o");
668 116 : load_signature.parameter_types.types.push_back(class_type);
669 58 : load_signature.parameter_types.var_args = false;
670 58 : load_signature.return_type = field.name_and_type.type;
671 : Statement* load_body =
672 : MakeNode<ReturnStatement>(MakeNode<LoadObjectFieldExpression>(
673 116 : parameter, field.name_and_type.name));
674 : Declarations::DeclareMacro(load_macro_name, base::nullopt, load_signature,
675 174 : false, load_body, load_operator_name);
676 :
677 : // Store accessor
678 : IdentifierExpression* value = MakeNode<IdentifierExpression>(
679 174 : std::vector<std::string>{}, std::string{"v"});
680 : std::string store_macro_name =
681 116 : "Store" + class_type->name() + camel_field_name;
682 116 : std::string store_operator_name = "." + field.name_and_type.name + "=";
683 58 : Signature store_signature;
684 116 : store_signature.parameter_names.push_back("o");
685 116 : store_signature.parameter_names.push_back("v");
686 116 : store_signature.parameter_types.types.push_back(class_type);
687 58 : store_signature.parameter_types.types.push_back(field.name_and_type.type);
688 58 : store_signature.parameter_types.var_args = false;
689 : // TODO(danno): Store macros probably should return their value argument
690 58 : store_signature.return_type = TypeOracle::GetVoidType();
691 : Statement* store_body =
692 : MakeNode<ExpressionStatement>(MakeNode<StoreObjectFieldExpression>(
693 116 : parameter, field.name_and_type.name, value));
694 : Declarations::DeclareMacro(store_macro_name, base::nullopt, store_signature,
695 174 : false, store_body, store_operator_name);
696 : }
697 :
698 19 : DeclareMethods(class_type, class_declaration->methods);
699 19 : }
700 :
701 1 : void DeclarationVisitor::FinalizeStructsAndClasses() {
702 15 : for (auto current_struct_info : struct_declarations_) {
703 : Scope* scope;
704 : StructDeclaration* struct_declaration;
705 : StructType* struct_type;
706 : std::tie(scope, struct_declaration, struct_type) = current_struct_info;
707 13 : CurrentScope::Scope scope_activator(scope);
708 13 : FinalizeStructFieldsAndMethods(struct_type, struct_declaration);
709 : }
710 :
711 21 : for (auto current_class_info : class_declarations_) {
712 : Scope* scope;
713 : ClassDeclaration* class_declaration;
714 : ClassType* class_type;
715 : std::tie(scope, class_declaration, class_type) = current_class_info;
716 19 : CurrentScope::Scope scope_activator(scope);
717 19 : CurrentSourcePosition::Scope position_activator(class_declaration->pos);
718 19 : FinalizeClassFieldsAndMethods(class_type, class_declaration);
719 : }
720 1 : }
721 :
722 : } // namespace torque
723 : } // namespace internal
724 9114 : } // namespace v8
|