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 229472 : 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 101134 : explicit QualifiedName(std::string name)
36 202268 : : QualifiedName({}, std::move(name)) {}
37 :
38 : friend std::ostream& operator<<(std::ostream& os, const QualifiedName& name);
39 : };
40 :
41 : class Declarable {
42 : public:
43 7169 : 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 27976 : bool IsNamespace() const { return kind() == kNamespace; }
58 17811 : bool IsMacro() const { return kind() == kMacro || kind() == kMethod; }
59 434 : bool IsMethod() const { return kind() == kMethod; }
60 62 : bool IsIntrinsic() const { return kind() == kIntrinsic; }
61 28224 : bool IsBuiltin() const { return kind() == kBuiltin; }
62 82 : bool IsRuntimeFunction() const { return kind() == kRuntimeFunction; }
63 32333 : bool IsGeneric() const { return kind() == kGeneric; }
64 90579 : bool IsTypeAlias() const { return kind() == kTypeAlias; }
65 982 : bool IsExternConstant() const { return kind() == kExternConstant; }
66 787 : bool IsNamespaceConstant() const { return kind() == kNamespaceConstant; }
67 982 : bool IsValue() const { return IsExternConstant() || IsNamespaceConstant(); }
68 46 : bool IsScope() const { return IsNamespace() || IsCallable(); }
69 12037 : bool IsCallable() const {
70 12037 : return IsMacro() || IsBuiltin() || IsRuntimeFunction() || IsIntrinsic() ||
71 12037 : IsMethod();
72 : }
73 0 : virtual const char* type_name() const { return "<<unknown>>"; }
74 : Scope* ParentScope() const { return parent_scope_; }
75 : const SourcePosition& pos() const { return pos_; }
76 :
77 : protected:
78 21507 : explicit Declarable(Kind kind) : kind_(kind) {}
79 :
80 : private:
81 : const Kind kind_;
82 : 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 6332 : class Scope : public Declarable {
108 : public:
109 92 : DECLARE_DECLARABLE_BOILERPLATE(Scope, scope);
110 6332 : explicit Scope(Declarable::Kind kind) : Declarable(kind) {}
111 :
112 168478 : std::vector<Declarable*> LookupShallow(const QualifiedName& name) {
113 336864 : if (name.namespace_qualification.empty()) return declarations_[name.name];
114 : Scope* child = nullptr;
115 322 : for (Declarable* declarable :
116 46 : declarations_[name.namespace_qualification.front()]) {
117 46 : if (Scope* scope = Scope::DynamicCast(declarable)) {
118 46 : if (child != nullptr) {
119 : ReportError("ambiguous reference to scope ",
120 0 : name.namespace_qualification.front());
121 : }
122 : child = scope;
123 : }
124 : }
125 138 : if (child == nullptr) return {};
126 : return child->LookupShallow(
127 : QualifiedName({name.namespace_qualification.begin() + 1,
128 : name.namespace_qualification.end()},
129 138 : name.name));
130 : }
131 :
132 164330 : std::vector<Declarable*> Lookup(const QualifiedName& name) {
133 : std::vector<Declarable*> result;
134 164330 : if (ParentScope()) {
135 105924 : result = ParentScope()->Lookup(name);
136 : }
137 614134 : for (Declarable* declarable : LookupShallow(name)) {
138 121144 : result.push_back(declarable);
139 : }
140 164330 : return result;
141 : }
142 : template <class T>
143 828 : T* AddDeclarable(const std::string& name, T* declarable) {
144 9570 : declarations_[name].push_back(declarable);
145 938 : return declarable;
146 : }
147 :
148 : private:
149 : std::unordered_map<std::string, std::vector<Declarable*>> declarations_;
150 : };
151 :
152 4348 : class Namespace : public Scope {
153 : public:
154 55860 : DECLARE_DECLARABLE_BOILERPLATE(Namespace, namespace);
155 2169 : explicit Namespace(const std::string& name)
156 2169 : : Scope(Declarable::kNamespace), name_(name) {}
157 : const std::string& name() const { return name_; }
158 1323 : std::string ExternalName() const {
159 2646 : return CamelifyString(name()) + "BuiltinsFromDSLAssembler";
160 : }
161 : std::ostream& source_stream() { return source_stream_; }
162 : std::ostream& header_stream() { return header_stream_; }
163 : std::string source() { return source_stream_.str(); }
164 : std::string header() { return header_stream_.str(); }
165 :
166 : private:
167 : std::string name_;
168 : std::stringstream header_stream_;
169 : std::stringstream source_stream_;
170 : };
171 :
172 6850 : inline Namespace* CurrentNamespace() {
173 6850 : Scope* scope = CurrentScope::Get();
174 : while (true) {
175 8190 : if (Namespace* n = Namespace::DynamicCast(scope)) {
176 6850 : return n;
177 : }
178 1340 : scope = scope->ParentScope();
179 1340 : }
180 : }
181 :
182 220 : class Value : public Declarable {
183 : public:
184 1964 : DECLARE_DECLARABLE_BOILERPLATE(Value, value);
185 : const std::string& name() const { return name_; }
186 0 : virtual bool IsConst() const { return true; }
187 470 : VisitResult value() const { return *value_; }
188 : const Type* type() const { return type_; }
189 :
190 : void set_value(VisitResult value) {
191 : DCHECK(!value_);
192 : value_ = value;
193 : }
194 :
195 : protected:
196 110 : Value(Kind kind, const Type* type, const std::string& name)
197 110 : : Declarable(kind), type_(type), name_(name) {}
198 :
199 : private:
200 : const Type* type_;
201 : std::string name_;
202 : base::Optional<VisitResult> value_;
203 : };
204 :
205 120 : class NamespaceConstant : public Value {
206 : public:
207 1574 : DECLARE_DECLARABLE_BOILERPLATE(NamespaceConstant, constant);
208 :
209 : const std::string& constant_name() const { return constant_name_; }
210 : Expression* body() { return body_; }
211 : std::string ExternalAssemblerName() const {
212 317 : return Namespace::cast(ParentScope())->ExternalName();
213 : }
214 :
215 : private:
216 : friend class Declarations;
217 : explicit NamespaceConstant(std::string constant_name, const Type* type,
218 : Expression* body)
219 : : Value(Declarable::kNamespaceConstant, type, constant_name),
220 : constant_name_(std::move(constant_name)),
221 80 : body_(body) {}
222 :
223 : std::string constant_name_;
224 : Expression* body_;
225 : };
226 :
227 70 : class ExternConstant : public Value {
228 : public:
229 0 : DECLARE_DECLARABLE_BOILERPLATE(ExternConstant, constant);
230 :
231 : private:
232 : friend class Declarations;
233 70 : explicit ExternConstant(std::string name, const Type* type, std::string value)
234 70 : : Value(Declarable::kExternConstant, type, std::move(name)) {
235 70 : set_value(VisitResult(type, std::move(value)));
236 70 : }
237 : };
238 :
239 1994 : class Callable : public Scope {
240 : public:
241 12037 : DECLARE_DECLARABLE_BOILERPLATE(Callable, callable);
242 : const std::string& ExternalName() const { return external_name_; }
243 : const std::string& ReadableName() const { return readable_name_; }
244 : const Signature& signature() const { return signature_; }
245 : const NameVector& parameter_names() const {
246 : return signature_.parameter_names;
247 : }
248 : bool HasReturnValue() const {
249 574 : return !signature_.return_type->IsVoidOrNever();
250 : }
251 574 : void IncrementReturns() { ++returns_; }
252 : bool HasReturns() const { return returns_; }
253 : bool IsTransitioning() const { return transitioning_; }
254 : base::Optional<Statement*> body() const { return body_; }
255 1939 : bool IsExternal() const { return !body_.has_value(); }
256 415 : virtual bool ShouldBeInlined() const { return false; }
257 8 : bool IsConstructor() const { return readable_name_ == kConstructMethodName; }
258 :
259 : protected:
260 997 : Callable(Declarable::Kind kind, std::string external_name,
261 : std::string readable_name, Signature signature, bool transitioning,
262 : base::Optional<Statement*> body)
263 : : Scope(kind),
264 : external_name_(std::move(external_name)),
265 :
266 : readable_name_(std::move(readable_name)),
267 : signature_(std::move(signature)),
268 : transitioning_(transitioning),
269 : returns_(0),
270 1994 : body_(body) {
271 : DCHECK(!body || *body);
272 997 : }
273 :
274 : private:
275 : std::string external_name_;
276 : std::string readable_name_;
277 : Signature signature_;
278 : bool transitioning_;
279 : size_t returns_;
280 : base::Optional<Statement*> body_;
281 : };
282 :
283 2389 : class Macro : public Callable {
284 : public:
285 9256 : DECLARE_DECLARABLE_BOILERPLATE(Macro, macro);
286 11588 : bool ShouldBeInlined() const override {
287 25255 : for (const LabelDeclaration& label : signature().labels) {
288 3715 : for (const Type* type : label.types) {
289 98 : if (type->IsStructType()) return true;
290 : }
291 : }
292 : return Callable::ShouldBeInlined();
293 : }
294 :
295 : const std::string& external_assembler_name() const {
296 : return external_assembler_name_;
297 : }
298 :
299 : protected:
300 803 : Macro(Declarable::Kind kind, std::string external_name,
301 : std::string readable_name, std::string external_assembler_name,
302 : const Signature& signature, bool transitioning,
303 : base::Optional<Statement*> body)
304 : : Callable(kind, std::move(external_name), std::move(readable_name),
305 : signature, transitioning, body),
306 3212 : external_assembler_name_(std::move(external_assembler_name)) {
307 803 : if (signature.parameter_types.var_args) {
308 0 : ReportError("Varargs are not supported for macros.");
309 : }
310 803 : }
311 :
312 : private:
313 : friend class Declarations;
314 783 : Macro(std::string external_name, std::string readable_name,
315 : std::string external_assembler_name, const Signature& signature,
316 : bool transitioning, base::Optional<Statement*> body)
317 : : Macro(Declarable::kMacro, std::move(external_name),
318 : std::move(readable_name), external_assembler_name, signature,
319 3915 : transitioning, body) {}
320 :
321 : std::string external_assembler_name_;
322 : };
323 :
324 20 : class Method : public Macro {
325 : public:
326 868 : DECLARE_DECLARABLE_BOILERPLATE(Method, Method);
327 136 : bool ShouldBeInlined() const override {
328 272 : return Macro::ShouldBeInlined() ||
329 272 : signature().parameter_types.types[0]->IsStructType();
330 : }
331 : AggregateType* aggregate_type() const { return aggregate_type_; }
332 :
333 : private:
334 : friend class Declarations;
335 20 : Method(AggregateType* aggregate_type, std::string external_name,
336 : std::string readable_name, std::string external_assembler_name,
337 : const Signature& signature, bool transitioning, Statement* body)
338 : : Macro(Declarable::kMethod, std::move(external_name),
339 : std::move(readable_name), std::move(external_assembler_name),
340 : signature, transitioning, body),
341 100 : aggregate_type_(aggregate_type) {}
342 : AggregateType* aggregate_type_;
343 : };
344 :
345 134 : class Builtin : public Callable {
346 : public:
347 : enum Kind { kStub, kFixedArgsJavaScript, kVarArgsJavaScript };
348 56448 : DECLARE_DECLARABLE_BOILERPLATE(Builtin, builtin);
349 : Kind kind() const { return kind_; }
350 : bool IsStub() const { return kind_ == kStub; }
351 : bool IsVarArgsJavaScript() const { return kind_ == kVarArgsJavaScript; }
352 : bool IsFixedArgsJavaScript() const { return kind_ == kFixedArgsJavaScript; }
353 :
354 : private:
355 : friend class Declarations;
356 134 : Builtin(std::string external_name, std::string readable_name,
357 : Builtin::Kind kind, const Signature& signature, bool transitioning,
358 : base::Optional<Statement*> body)
359 : : Callable(Declarable::kBuiltin, std::move(external_name),
360 : std::move(readable_name), signature, transitioning, body),
361 536 : kind_(kind) {}
362 :
363 : Kind kind_;
364 : };
365 :
366 11 : class RuntimeFunction : public Callable {
367 : public:
368 164 : DECLARE_DECLARABLE_BOILERPLATE(RuntimeFunction, runtime);
369 :
370 : private:
371 : friend class Declarations;
372 11 : RuntimeFunction(const std::string& name, const Signature& signature,
373 : bool transitioning)
374 : : Callable(Declarable::kRuntimeFunction, name, name, signature,
375 33 : transitioning, base::nullopt) {}
376 : };
377 :
378 49 : class Intrinsic : public Callable {
379 : public:
380 124 : DECLARE_DECLARABLE_BOILERPLATE(Intrinsic, intrinsic);
381 :
382 : private:
383 : friend class Declarations;
384 49 : Intrinsic(std::string name, const Signature& signature)
385 : : Callable(Declarable::kIntrinsic, name, name, signature, false,
386 147 : base::nullopt) {
387 49 : if (signature.parameter_types.var_args) {
388 0 : ReportError("Varargs are not supported for intrinsics.");
389 : }
390 49 : }
391 : };
392 :
393 144 : class Generic : public Declarable {
394 : public:
395 64666 : DECLARE_DECLARABLE_BOILERPLATE(Generic, generic);
396 :
397 : GenericDeclaration* declaration() const { return declaration_; }
398 : const std::vector<std::string> generic_parameters() const {
399 : return declaration()->generic_parameters;
400 : }
401 : const std::string& name() const { return name_; }
402 : void AddSpecialization(const TypeVector& type_arguments,
403 : Callable* specialization) {
404 : DCHECK_EQ(0, specializations_.count(type_arguments));
405 302 : specializations_[type_arguments] = specialization;
406 : }
407 16019 : base::Optional<Callable*> GetSpecialization(
408 : const TypeVector& type_arguments) const {
409 : auto it = specializations_.find(type_arguments);
410 16019 : if (it != specializations_.end()) return it->second;
411 : return base::nullopt;
412 : }
413 : base::Optional<TypeVector> InferSpecializationTypes(
414 : const TypeVector& explicit_specialization_types,
415 : const TypeVector& arguments);
416 :
417 : private:
418 : friend class Declarations;
419 48 : Generic(const std::string& name, GenericDeclaration* declaration)
420 : : Declarable(Declarable::kGeneric),
421 : name_(name),
422 96 : declaration_(declaration) {}
423 : base::Optional<const Type*> InferTypeArgument(size_t i,
424 : const TypeVector& arguments);
425 :
426 : std::string name_;
427 : std::unordered_map<TypeVector, Callable*, base::hash<TypeVector>>
428 : specializations_;
429 : GenericDeclaration* declaration_;
430 : };
431 :
432 : struct SpecializationKey {
433 : Generic* generic;
434 : TypeVector specialized_types;
435 : };
436 :
437 7690 : class TypeAlias : public Declarable {
438 : public:
439 181158 : DECLARE_DECLARABLE_BOILERPLATE(TypeAlias, type_alias);
440 :
441 : const Type* type() const { return type_; }
442 : bool IsRedeclaration() const { return redeclaration_; }
443 :
444 : private:
445 : friend class Declarations;
446 : explicit TypeAlias(const Type* type, bool redeclaration)
447 : : Declarable(Declarable::kTypeAlias),
448 : type_(type),
449 3845 : redeclaration_(redeclaration) {}
450 :
451 : const Type* type_;
452 : bool redeclaration_;
453 : };
454 :
455 : std::ostream& operator<<(std::ostream& os, const Callable& m);
456 : std::ostream& operator<<(std::ostream& os, const Builtin& b);
457 : std::ostream& operator<<(std::ostream& os, const RuntimeFunction& b);
458 : std::ostream& operator<<(std::ostream& os, const Generic& g);
459 :
460 : #undef DECLARE_DECLARABLE_BOILERPLATE
461 :
462 : } // namespace torque
463 : } // namespace internal
464 : } // namespace v8
465 :
466 : #endif // V8_TORQUE_DECLARABLE_H_
|