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 : #ifndef V8_TORQUE_DECLARABLE_H_
6 : #define V8_TORQUE_DECLARABLE_H_
7 :
8 : #include <cassert>
9 : #include <string>
10 : #include <unordered_map>
11 :
12 : #include "src/base/functional.h"
13 : #include "src/base/logging.h"
14 : #include "src/torque/ast.h"
15 : #include "src/torque/types.h"
16 : #include "src/torque/utils.h"
17 :
18 : namespace v8 {
19 : namespace internal {
20 : namespace torque {
21 :
22 : class Scope;
23 : class Namespace;
24 :
25 : DECLARE_CONTEXTUAL_VARIABLE(CurrentScope, Scope*);
26 :
27 331366 : struct QualifiedName {
28 : std::vector<std::string> namespace_qualification;
29 : std::string name;
30 :
31 : QualifiedName(std::vector<std::string> namespace_qualification,
32 : std::string name)
33 : : namespace_qualification(std::move(namespace_qualification)),
34 : name(std::move(name)) {}
35 147616 : explicit QualifiedName(std::string name)
36 295232 : : QualifiedName({}, std::move(name)) {}
37 :
38 : friend std::ostream& operator<<(std::ostream& os, const QualifiedName& name);
39 : };
40 :
41 : class Declarable {
42 : public:
43 10206 : virtual ~Declarable() = default;
44 : enum Kind {
45 : kNamespace,
46 : kMacro,
47 : kMethod,
48 : kBuiltin,
49 : kRuntimeFunction,
50 : kIntrinsic,
51 : kGeneric,
52 : kTypeAlias,
53 : kExternConstant,
54 : kNamespaceConstant
55 : };
56 : Kind kind() const { return kind_; }
57 : bool IsNamespace() const { return kind() == kNamespace; }
58 27175 : bool IsMacro() const { return kind() == kMacro || kind() == kMethod; }
59 : bool IsMethod() const { return kind() == kMethod; }
60 : bool IsIntrinsic() const { return kind() == kIntrinsic; }
61 : bool IsBuiltin() const { return kind() == kBuiltin; }
62 : bool IsRuntimeFunction() const { return kind() == kRuntimeFunction; }
63 : bool IsGeneric() const { return kind() == kGeneric; }
64 : bool IsTypeAlias() const { return kind() == kTypeAlias; }
65 : bool IsExternConstant() const { return kind() == kExternConstant; }
66 : bool IsNamespaceConstant() const { return kind() == kNamespaceConstant; }
67 1275 : bool IsValue() const { return IsExternConstant() || IsNamespaceConstant(); }
68 134 : bool IsScope() const { return IsNamespace() || IsCallable(); }
69 : bool IsCallable() const {
70 18653 : return IsMacro() || IsBuiltin() || IsRuntimeFunction() || IsIntrinsic() ||
71 : IsMethod();
72 : }
73 0 : virtual const char* type_name() const { return "<<unknown>>"; }
74 : Scope* ParentScope() const { return parent_scope_; }
75 7189 : const SourcePosition& pos() const { return pos_; }
76 :
77 : protected:
78 30618 : explicit Declarable(Kind kind) : kind_(kind) {}
79 :
80 : private:
81 : const Kind kind_;
82 10206 : Scope* const parent_scope_ = CurrentScope::Get();
83 : SourcePosition pos_ = CurrentSourcePosition::Get();
84 : };
85 :
86 : #define DECLARE_DECLARABLE_BOILERPLATE(x, y) \
87 : static x* cast(Declarable* declarable) { \
88 : DCHECK(declarable->Is##x()); \
89 : return static_cast<x*>(declarable); \
90 : } \
91 : static const x* cast(const Declarable* declarable) { \
92 : DCHECK(declarable->Is##x()); \
93 : return static_cast<const x*>(declarable); \
94 : } \
95 : const char* type_name() const override { return #y; } \
96 : static x* DynamicCast(Declarable* declarable) { \
97 : if (!declarable) return nullptr; \
98 : if (!declarable->Is##x()) return nullptr; \
99 : return static_cast<x*>(declarable); \
100 : } \
101 : static const x* DynamicCast(const Declarable* declarable) { \
102 : if (!declarable) return nullptr; \
103 : if (!declarable->Is##x()) return nullptr; \
104 : return static_cast<const x*>(declarable); \
105 : }
106 :
107 9414 : class Scope : public Declarable {
108 : public:
109 134 : DECLARE_DECLARABLE_BOILERPLATE(Scope, scope)
110 4707 : explicit Scope(Declarable::Kind kind) : Declarable(kind) {}
111 :
112 238777 : std::vector<Declarable*> LookupShallow(const QualifiedName& name) {
113 477189 : if (name.namespace_qualification.empty()) return declarations_[name.name];
114 : Scope* child = nullptr;
115 499 : for (Declarable* declarable :
116 134 : declarations_[name.namespace_qualification.front()]) {
117 134 : if (Scope* scope = Scope::DynamicCast(declarable)) {
118 134 : if (child != nullptr) {
119 : ReportError("ambiguous reference to scope ",
120 0 : name.namespace_qualification.front());
121 : }
122 : child = scope;
123 : }
124 : }
125 365 : if (child == nullptr) return {};
126 : return child->LookupShallow(
127 : QualifiedName({name.namespace_qualification.begin() + 1,
128 : name.namespace_qualification.end()},
129 268 : name.name));
130 : }
131 :
132 232995 : std::vector<Declarable*> Lookup(const QualifiedName& name) {
133 : std::vector<Declarable*> result;
134 232995 : if (ParentScope()) {
135 144604 : result = ParentScope()->Lookup(name);
136 : }
137 642043 : for (Declarable* declarable : LookupShallow(name)) {
138 176053 : result.push_back(declarable);
139 : }
140 232995 : return result;
141 : }
142 : template <class T>
143 : T* AddDeclarable(const std::string& name, T* declarable) {
144 14820 : declarations_[name].push_back(declarable);
145 120 : return declarable;
146 : }
147 :
148 : private:
149 : std::unordered_map<std::string, std::vector<Declarable*>> declarations_;
150 : };
151 :
152 6160 : class Namespace : public Scope {
153 : public:
154 110666 : DECLARE_DECLARABLE_BOILERPLATE(Namespace, namespace)
155 3059 : explicit Namespace(const std::string& name)
156 6118 : : Scope(Declarable::kNamespace), name_(name) {}
157 4492 : const std::string& name() const { return name_; }
158 2763 : std::string ExternalName() const {
159 5526 : return CamelifyString(name()) + "BuiltinsFromDSLAssembler";
160 : }
161 : bool IsDefaultNamespace() const;
162 : bool IsTestNamespace() const;
163 7828 : std::ostream& source_stream() { return source_stream_; }
164 3294 : std::ostream& header_stream() { return header_stream_; }
165 : std::string source() { return source_stream_.str(); }
166 : std::string header() { return header_stream_.str(); }
167 :
168 : private:
169 : std::string name_;
170 : std::stringstream header_stream_;
171 : std::stringstream source_stream_;
172 : };
173 :
174 13008 : inline Namespace* CurrentNamespace() {
175 13008 : Scope* scope = CurrentScope::Get();
176 2095 : while (true) {
177 15103 : if (Namespace* n = Namespace::DynamicCast(scope)) {
178 13008 : return n;
179 : }
180 : scope = scope->ParentScope();
181 : }
182 : }
183 :
184 240 : class Value : public Declarable {
185 : public:
186 2550 : DECLARE_DECLARABLE_BOILERPLATE(Value, value)
187 : const Identifier* name() const { return name_; }
188 0 : virtual bool IsConst() const { return true; }
189 : VisitResult value() const { return *value_; }
190 : const Type* type() const { return type_; }
191 :
192 : void set_value(VisitResult value) {
193 : DCHECK(!value_);
194 : value_ = value;
195 : }
196 :
197 : protected:
198 : Value(Kind kind, const Type* type, Identifier* name)
199 120 : : Declarable(kind), type_(type), name_(name) {}
200 :
201 : private:
202 : const Type* type_;
203 : Identifier* name_;
204 : base::Optional<VisitResult> value_;
205 : };
206 :
207 62 : class NamespaceConstant : public Value {
208 : public:
209 997 : DECLARE_DECLARABLE_BOILERPLATE(NamespaceConstant, constant)
210 :
211 : Expression* body() { return body_; }
212 : std::string ExternalAssemblerName() const {
213 385 : return Namespace::cast(ParentScope())->ExternalName();
214 : }
215 :
216 : private:
217 : friend class Declarations;
218 : explicit NamespaceConstant(Identifier* constant_name, const Type* type,
219 : Expression* body)
220 : : Value(Declarable::kNamespaceConstant, type, constant_name),
221 31 : body_(body) {}
222 :
223 : Expression* body_;
224 : };
225 :
226 178 : class ExternConstant : public Value {
227 : public:
228 0 : DECLARE_DECLARABLE_BOILERPLATE(ExternConstant, constant)
229 :
230 : private:
231 : friend class Declarations;
232 89 : explicit ExternConstant(Identifier* name, const Type* type, std::string value)
233 89 : : Value(Declarable::kExternConstant, type, name) {
234 89 : set_value(VisitResult(type, std::move(value)));
235 89 : }
236 : };
237 :
238 3296 : class Callable : public Scope {
239 : public:
240 37306 : DECLARE_DECLARABLE_BOILERPLATE(Callable, callable)
241 1467 : const std::string& ExternalName() const { return external_name_; }
242 642 : const std::string& ReadableName() const { return readable_name_; }
243 19611 : const Signature& signature() const { return signature_; }
244 : const NameVector& parameter_names() const {
245 958 : return signature_.parameter_names;
246 : }
247 : bool HasReturnValue() const {
248 1016 : return !signature_.return_type->IsVoidOrNever();
249 : }
250 1016 : void IncrementReturns() { ++returns_; }
251 : bool HasReturns() const { return returns_; }
252 : bool IsTransitioning() const { return transitioning_; }
253 1244 : base::Optional<Statement*> body() const { return body_; }
254 466 : bool IsExternal() const { return !body_.has_value(); }
255 2757 : virtual bool ShouldBeInlined() const { return false; }
256 10371 : virtual bool ShouldGenerateExternalCode() const { return !ShouldBeInlined(); }
257 :
258 : protected:
259 1648 : Callable(Declarable::Kind kind, std::string external_name,
260 : std::string readable_name, Signature signature, bool transitioning,
261 : base::Optional<Statement*> body)
262 : : Scope(kind),
263 : external_name_(std::move(external_name)),
264 :
265 : readable_name_(std::move(readable_name)),
266 : signature_(std::move(signature)),
267 : transitioning_(transitioning),
268 : returns_(0),
269 3296 : body_(body) {
270 : DCHECK(!body || *body);
271 1648 : }
272 :
273 : private:
274 : std::string external_name_;
275 : std::string readable_name_;
276 : Signature signature_;
277 : bool transitioning_;
278 : size_t returns_;
279 : base::Optional<Statement*> body_;
280 : };
281 :
282 4078 : class Macro : public Callable {
283 : public:
284 12996 : DECLARE_DECLARABLE_BOILERPLATE(Macro, macro)
285 22509 : bool ShouldBeInlined() const override {
286 26113 : for (const LabelDeclaration& label : signature().labels) {
287 3261 : for (const Type* type : label.types) {
288 348 : if (type->IsStructType()) return true;
289 : }
290 : }
291 : return Callable::ShouldBeInlined();
292 : }
293 :
294 : const std::string& external_assembler_name() const {
295 : return external_assembler_name_;
296 : }
297 :
298 : protected:
299 1370 : Macro(Declarable::Kind kind, std::string external_name,
300 : std::string readable_name, std::string external_assembler_name,
301 : const Signature& signature, bool transitioning,
302 : base::Optional<Statement*> body)
303 : : Callable(kind, std::move(external_name), std::move(readable_name),
304 : signature, transitioning, body),
305 5480 : external_assembler_name_(std::move(external_assembler_name)) {
306 1370 : if (signature.parameter_types.var_args) {
307 0 : ReportError("Varargs are not supported for macros.");
308 : }
309 1370 : }
310 :
311 : private:
312 : friend class Declarations;
313 1338 : Macro(std::string external_name, std::string readable_name,
314 : std::string external_assembler_name, const Signature& signature,
315 : bool transitioning, base::Optional<Statement*> body)
316 : : Macro(Declarable::kMacro, std::move(external_name),
317 : std::move(readable_name), external_assembler_name, signature,
318 6690 : transitioning, body) {}
319 :
320 : std::string external_assembler_name_;
321 : };
322 :
323 32 : class Method : public Macro {
324 : public:
325 958 : DECLARE_DECLARABLE_BOILERPLATE(Method, Method)
326 691 : bool ShouldBeInlined() const override {
327 1382 : return Macro::ShouldBeInlined() ||
328 : signature()
329 691 : .parameter_types.types[signature().implicit_count]
330 1382 : ->IsStructType();
331 : }
332 : AggregateType* aggregate_type() const { return aggregate_type_; }
333 :
334 : private:
335 : friend class Declarations;
336 32 : Method(AggregateType* aggregate_type, std::string external_name,
337 : std::string readable_name, std::string external_assembler_name,
338 : const Signature& signature, bool transitioning, Statement* body)
339 : : Macro(Declarable::kMethod, std::move(external_name),
340 : std::move(readable_name), std::move(external_assembler_name),
341 : signature, transitioning, body),
342 160 : aggregate_type_(aggregate_type) {}
343 : AggregateType* aggregate_type_;
344 : };
345 :
346 196 : class Builtin : public Callable {
347 : public:
348 : enum Kind { kStub, kFixedArgsJavaScript, kVarArgsJavaScript };
349 39590 : DECLARE_DECLARABLE_BOILERPLATE(Builtin, builtin)
350 : Kind kind() const { return kind_; }
351 : bool IsStub() const { return kind_ == kStub; }
352 : bool IsVarArgsJavaScript() const { return kind_ == kVarArgsJavaScript; }
353 : bool IsFixedArgsJavaScript() const { return kind_ == kFixedArgsJavaScript; }
354 :
355 : private:
356 : friend class Declarations;
357 196 : Builtin(std::string external_name, std::string readable_name,
358 : Builtin::Kind kind, const Signature& signature, bool transitioning,
359 : base::Optional<Statement*> body)
360 : : Callable(Declarable::kBuiltin, std::move(external_name),
361 : std::move(readable_name), signature, transitioning, body),
362 784 : kind_(kind) {}
363 :
364 : Kind kind_;
365 : };
366 :
367 16 : class RuntimeFunction : public Callable {
368 : public:
369 116 : DECLARE_DECLARABLE_BOILERPLATE(RuntimeFunction, runtime)
370 :
371 : private:
372 : friend class Declarations;
373 16 : RuntimeFunction(const std::string& name, const Signature& signature,
374 : bool transitioning)
375 : : Callable(Declarable::kRuntimeFunction, name, name, signature,
376 64 : transitioning, base::nullopt) {}
377 : };
378 :
379 66 : class Intrinsic : public Callable {
380 : public:
381 93 : DECLARE_DECLARABLE_BOILERPLATE(Intrinsic, intrinsic)
382 :
383 : private:
384 : friend class Declarations;
385 66 : Intrinsic(std::string name, const Signature& signature)
386 : : Callable(Declarable::kIntrinsic, name, name, signature, false,
387 264 : base::nullopt) {
388 66 : if (signature.parameter_types.var_args) {
389 0 : ReportError("Varargs are not supported for intrinsics.");
390 : }
391 66 : }
392 : };
393 :
394 135 : class Generic : public Declarable {
395 : public:
396 47674 : DECLARE_DECLARABLE_BOILERPLATE(Generic, generic)
397 :
398 : GenericDeclaration* declaration() const { return declaration_; }
399 : const std::vector<Identifier*> generic_parameters() const {
400 : return declaration()->generic_parameters;
401 : }
402 0 : const std::string& name() const { return name_; }
403 : void AddSpecialization(const TypeVector& type_arguments,
404 : Callable* specialization) {
405 : DCHECK_EQ(0, specializations_.count(type_arguments));
406 319 : specializations_[type_arguments] = specialization;
407 : }
408 : base::Optional<Callable*> GetSpecialization(
409 : const TypeVector& type_arguments) const {
410 : auto it = specializations_.find(type_arguments);
411 29812 : if (it != specializations_.end()) return it->second;
412 15751 : return base::nullopt;
413 : }
414 : base::Optional<TypeVector> InferSpecializationTypes(
415 : const TypeVector& explicit_specialization_types,
416 : const TypeVector& arguments);
417 :
418 : private:
419 : friend class Declarations;
420 45 : Generic(const std::string& name, GenericDeclaration* declaration)
421 : : Declarable(Declarable::kGeneric),
422 : name_(name),
423 90 : declaration_(declaration) {}
424 : base::Optional<const Type*> InferTypeArgument(size_t i,
425 : const TypeVector& arguments);
426 :
427 : std::string name_;
428 : std::unordered_map<TypeVector, Callable*, base::hash<TypeVector>>
429 : specializations_;
430 : GenericDeclaration* declaration_;
431 : };
432 :
433 5199 : struct SpecializationKey {
434 : Generic* generic;
435 : TypeVector specialized_types;
436 : };
437 :
438 10668 : class TypeAlias : public Declarable {
439 : public:
440 130685 : DECLARE_DECLARABLE_BOILERPLATE(TypeAlias, type_alias)
441 :
442 : const Type* type() const { return type_; }
443 : bool IsRedeclaration() const { return redeclaration_; }
444 : SourcePosition GetDeclarationPosition() const {
445 4 : return declaration_position_;
446 : }
447 :
448 : private:
449 : friend class Declarations;
450 : explicit TypeAlias(
451 : const Type* type, bool redeclaration,
452 : SourcePosition declaration_position = SourcePosition::Invalid())
453 : : Declarable(Declarable::kTypeAlias),
454 : type_(type),
455 : redeclaration_(redeclaration),
456 5334 : declaration_position_(declaration_position) {}
457 :
458 : const Type* type_;
459 : bool redeclaration_;
460 : const SourcePosition declaration_position_;
461 : };
462 :
463 : std::ostream& operator<<(std::ostream& os, const Callable& m);
464 : std::ostream& operator<<(std::ostream& os, const Builtin& b);
465 : std::ostream& operator<<(std::ostream& os, const RuntimeFunction& b);
466 : std::ostream& operator<<(std::ostream& os, const Generic& g);
467 :
468 : #undef DECLARE_DECLARABLE_BOILERPLATE
469 :
470 : } // namespace torque
471 : } // namespace internal
472 : } // namespace v8
473 :
474 : #endif // V8_TORQUE_DECLARABLE_H_
|