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 357624 : 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 160109 : explicit QualifiedName(std::string name)
36 320218 : : QualifiedName({}, std::move(name)) {}
37 :
38 : friend std::ostream& operator<<(std::ostream& os, const QualifiedName& name);
39 : };
40 :
41 : class Declarable {
42 : public:
43 10704 : 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 26448 : 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 1315 : bool IsValue() const { return IsExternConstant() || IsNamespaceConstant(); }
68 135 : bool IsScope() const { return IsNamespace() || IsCallable(); }
69 : bool IsCallable() const {
70 18167 : 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 7588 : const SourcePosition& pos() const { return pos_; }
76 :
77 : protected:
78 32112 : explicit Declarable(Kind kind) : kind_(kind) {}
79 :
80 : private:
81 : const Kind kind_;
82 10704 : 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 10004 : class Scope : public Declarable {
108 : public:
109 135 : DECLARE_DECLARABLE_BOILERPLATE(Scope, scope)
110 5002 : explicit Scope(Declarable::Kind kind) : Declarable(kind) {}
111 :
112 253274 : std::vector<Declarable*> LookupShallow(const QualifiedName& name) {
113 506181 : if (name.namespace_qualification.empty()) return declarations_[name.name];
114 : Scope* child = nullptr;
115 502 : for (Declarable* declarable :
116 135 : declarations_[name.namespace_qualification.front()]) {
117 135 : if (Scope* scope = Scope::DynamicCast(declarable)) {
118 135 : if (child != nullptr) {
119 : ReportError("ambiguous reference to scope ",
120 0 : name.namespace_qualification.front());
121 : }
122 : child = scope;
123 : }
124 : }
125 367 : if (child == nullptr) return {};
126 : return child->LookupShallow(
127 : QualifiedName({name.namespace_qualification.begin() + 1,
128 : name.namespace_qualification.end()},
129 405 : name.name));
130 : }
131 :
132 247285 : std::vector<Declarable*> Lookup(const QualifiedName& name) {
133 : std::vector<Declarable*> result;
134 247285 : if (ParentScope()) {
135 147292 : result = ParentScope()->Lookup(name);
136 : }
137 682314 : for (Declarable* declarable : LookupShallow(name)) {
138 187744 : result.push_back(declarable);
139 : }
140 247285 : return result;
141 : }
142 : template <class T>
143 : T* AddDeclarable(const std::string& name, T* declarable) {
144 14608 : declarations_[name].push_back(declarable);
145 130 : return declarable;
146 : }
147 :
148 : private:
149 : std::unordered_map<std::string, std::vector<Declarable*>> declarations_;
150 : };
151 :
152 6364 : class Namespace : public Scope {
153 : public:
154 127663 : DECLARE_DECLARABLE_BOILERPLATE(Namespace, namespace)
155 3160 : explicit Namespace(const std::string& name)
156 6320 : : Scope(Declarable::kNamespace), name_(name) {}
157 5260 : const std::string& name() const { return name_; }
158 3290 : std::string ExternalName() const {
159 6580 : return CamelifyString(name()) + "BuiltinsFromDSLAssembler";
160 : }
161 : bool IsDefaultNamespace() const;
162 : bool IsTestNamespace() const;
163 8857 : std::ostream& source_stream() { return source_stream_; }
164 3832 : 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 14929 : inline Namespace* CurrentNamespace() {
175 14929 : Scope* scope = CurrentScope::Get();
176 2225 : while (true) {
177 17154 : if (Namespace* n = Namespace::DynamicCast(scope)) {
178 14929 : return n;
179 : }
180 : scope = scope->ParentScope();
181 : }
182 : }
183 :
184 260 : class Value : public Declarable {
185 : public:
186 2630 : 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 130 : : Declarable(kind), type_(type), name_(name) {}
200 :
201 : private:
202 : const Type* type_;
203 : Identifier* name_;
204 : base::Optional<VisitResult> value_;
205 : };
206 :
207 66 : class NamespaceConstant : public Value {
208 : public:
209 1029 : DECLARE_DECLARABLE_BOILERPLATE(NamespaceConstant, constant)
210 :
211 : Expression* body() { return body_; }
212 : std::string ExternalAssemblerName() const {
213 400 : 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 33 : body_(body) {}
222 :
223 : Expression* body_;
224 : };
225 :
226 194 : class ExternConstant : public Value {
227 : public:
228 0 : DECLARE_DECLARABLE_BOILERPLATE(ExternConstant, constant)
229 :
230 : private:
231 : friend class Declarations;
232 97 : explicit ExternConstant(Identifier* name, const Type* type, std::string value)
233 97 : : Value(Declarable::kExternConstant, type, name) {
234 97 : set_value(VisitResult(type, std::move(value)));
235 97 : }
236 : };
237 :
238 3684 : class Callable : public Scope {
239 : public:
240 36334 : DECLARE_DECLARABLE_BOILERPLATE(Callable, callable)
241 1713 : const std::string& ExternalName() const { return external_name_; }
242 649 : const std::string& ReadableName() const { return readable_name_; }
243 19287 : const Signature& signature() const { return signature_; }
244 : const NameVector& parameter_names() const {
245 1120 : return signature_.parameter_names;
246 : }
247 : bool HasReturnValue() const {
248 1116 : return !signature_.return_type->IsVoidOrNever();
249 : }
250 1116 : void IncrementReturns() { ++returns_; }
251 : bool HasReturns() const { return returns_; }
252 : bool IsTransitioning() const { return transitioning_; }
253 1413 : base::Optional<Statement*> body() const { return body_; }
254 480 : bool IsExternal() const { return !body_.has_value(); }
255 2926 : virtual bool ShouldBeInlined() const { return false; }
256 11891 : virtual bool ShouldGenerateExternalCode() const { return !ShouldBeInlined(); }
257 :
258 : protected:
259 1842 : 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 3684 : body_(body) {
270 : DCHECK(!body || *body);
271 1842 : }
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 4605 : class Macro : public Callable {
283 : public:
284 12114 : DECLARE_DECLARABLE_BOILERPLATE(Macro, macro)
285 23451 : bool ShouldBeInlined() const override {
286 27208 : for (const LabelDeclaration& label : signature().labels) {
287 3329 : 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 1548 : 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 6192 : external_assembler_name_(std::move(external_assembler_name)) {
306 1548 : if (signature.parameter_types.var_args) {
307 0 : ReportError("Varargs are not supported for macros.");
308 : }
309 1548 : }
310 :
311 : private:
312 : friend class Declarations;
313 1509 : 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 7545 : transitioning, body) {}
319 :
320 : std::string external_assembler_name_;
321 : };
322 :
323 39 : class Method : public Macro {
324 : public:
325 1120 : DECLARE_DECLARABLE_BOILERPLATE(Method, Method)
326 776 : bool ShouldBeInlined() const override {
327 1552 : return Macro::ShouldBeInlined() ||
328 : signature()
329 776 : .parameter_types.types[signature().implicit_count]
330 1552 : ->IsStructType();
331 : }
332 : AggregateType* aggregate_type() const { return aggregate_type_; }
333 :
334 : private:
335 : friend class Declarations;
336 39 : 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 195 : aggregate_type_(aggregate_type) {}
343 : AggregateType* aggregate_type_;
344 : };
345 :
346 203 : class Builtin : public Callable {
347 : public:
348 : enum Kind { kStub, kFixedArgsJavaScript, kVarArgsJavaScript };
349 41471 : 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 203 : 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 812 : kind_(kind) {}
363 :
364 : Kind kind_;
365 : };
366 :
367 18 : class RuntimeFunction : public Callable {
368 : public:
369 132 : DECLARE_DECLARABLE_BOILERPLATE(RuntimeFunction, runtime)
370 :
371 : private:
372 : friend class Declarations;
373 18 : RuntimeFunction(const std::string& name, const Signature& signature,
374 : bool transitioning)
375 : : Callable(Declarable::kRuntimeFunction, name, name, signature,
376 72 : transitioning, base::nullopt) {}
377 : };
378 :
379 73 : class Intrinsic : public Callable {
380 : public:
381 105 : DECLARE_DECLARABLE_BOILERPLATE(Intrinsic, intrinsic)
382 :
383 : private:
384 : friend class Declarations;
385 73 : Intrinsic(std::string name, const Signature& signature)
386 : : Callable(Declarable::kIntrinsic, name, name, signature, false,
387 292 : base::nullopt) {
388 73 : if (signature.parameter_types.var_args) {
389 0 : ReportError("Varargs are not supported for intrinsics.");
390 : }
391 73 : }
392 : };
393 :
394 138 : class Generic : public Declarable {
395 : public:
396 47005 : 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 328 : specializations_[type_arguments] = specialization;
407 : }
408 : base::Optional<Callable*> GetSpecialization(
409 : const TypeVector& type_arguments) const {
410 : auto it = specializations_.find(type_arguments);
411 30041 : if (it != specializations_.end()) return it->second;
412 15309 : 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 46 : Generic(const std::string& name, GenericDeclaration* declaration)
421 : : Declarable(Declarable::kGeneric),
422 : name_(name),
423 92 : declaration_(declaration) {}
424 :
425 : std::string name_;
426 : std::unordered_map<TypeVector, Callable*, base::hash<TypeVector>>
427 : specializations_;
428 : GenericDeclaration* declaration_;
429 : };
430 :
431 5363 : struct SpecializationKey {
432 : Generic* generic;
433 : TypeVector specialized_types;
434 : };
435 :
436 11052 : class TypeAlias : public Declarable {
437 : public:
438 143125 : DECLARE_DECLARABLE_BOILERPLATE(TypeAlias, type_alias)
439 :
440 : const Type* type() const { return type_; }
441 : bool IsRedeclaration() const { return redeclaration_; }
442 : SourcePosition GetDeclarationPosition() const {
443 4 : return declaration_position_;
444 : }
445 :
446 : private:
447 : friend class Declarations;
448 : explicit TypeAlias(
449 : const Type* type, bool redeclaration,
450 : SourcePosition declaration_position = SourcePosition::Invalid())
451 : : Declarable(Declarable::kTypeAlias),
452 : type_(type),
453 : redeclaration_(redeclaration),
454 5526 : declaration_position_(declaration_position) {}
455 :
456 : const Type* type_;
457 : bool redeclaration_;
458 : const SourcePosition declaration_position_;
459 : };
460 :
461 : std::ostream& operator<<(std::ostream& os, const Callable& m);
462 : std::ostream& operator<<(std::ostream& os, const Builtin& b);
463 : std::ostream& operator<<(std::ostream& os, const RuntimeFunction& b);
464 : std::ostream& operator<<(std::ostream& os, const Generic& g);
465 :
466 : #undef DECLARE_DECLARABLE_BOILERPLATE
467 :
468 : } // namespace torque
469 : } // namespace internal
470 : } // namespace v8
471 :
472 : #endif // V8_TORQUE_DECLARABLE_H_
|