v8
V8 is Google’s open source high-performance JavaScript and WebAssembly engine, written in C++.
Loading...
Searching...
No Matches
implementation-visitor.h
Go to the documentation of this file.
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_IMPLEMENTATION_VISITOR_H_
6#define V8_TORQUE_IMPLEMENTATION_VISITOR_H_
7
8#include <memory>
9#include <optional>
10#include <string>
11
12#include "src/base/macros.h"
13#include "src/torque/ast.h"
14#include "src/torque/cfg.h"
19#include "src/torque/types.h"
20#include "src/torque/utils.h"
21
22namespace v8::internal::torque {
23
24template <typename T>
25class Binding;
26class LocalValue;
27class ImplementationVisitor;
28
29// LocationReference is the representation of an l-value, so a value that might
30// allow for assignment. For uniformity, this class can also represent
31// unassignable temporaries. Assignable values fall in two categories:
32// - stack ranges that represent mutable variables, including structs.
33// - field or element access expressions that generate operator calls.
35 public:
36 // An assignable stack range.
39 std::optional<Binding<LocalValue>*> binding = std::nullopt) {
40 DCHECK(variable.IsOnStack());
42 result.variable_ = std::move(variable);
43 result.binding_ = binding;
44 return result;
45 }
46 // An unassignable value. {description} is only used for error messages.
48 std::string description) {
50 result.temporary_ = std::move(temporary);
51 result.temporary_description_ = std::move(description);
52 return result;
53 }
54 // A heap reference, that is, a tagged value and an offset to encode an inner
55 // pointer.
61 result.heap_reference_ = std::move(heap_reference);
62 result.heap_reference_synchronization_ = synchronization;
63 return result;
64 }
65 // A reference to an array on the heap. That is, a tagged value, an offset to
66 // encode an inner pointer, and the number of elements.
78 result.eval_function_ = std::string{"[]"};
79 result.assign_function_ = std::string{"[]="};
80 result.call_arguments_ = {base, offset};
81 return result;
82 }
84 std::string fieldname) {
86 result.eval_function_ = "." + fieldname;
87 result.assign_function_ = "." + fieldname + "=";
88 result.call_arguments_ = {object};
89 return result;
90 }
92 BitField field) {
94 result.bit_field_struct_ = std::make_shared<LocationReference>(object);
95 result.bit_field_ = std::move(field);
96 return result;
97 }
98
99 bool IsConst() const {
100 if (IsHeapReference()) {
101 bool is_const;
102 bool success =
104 .has_value();
105 CHECK(success);
106 return is_const;
107 }
108 return IsTemporary();
109 }
110
111 bool IsVariableAccess() const { return variable_.has_value(); }
112 const VisitResult& variable() const {
114 return *variable_;
115 }
116 bool IsTemporary() const { return temporary_.has_value(); }
117 const VisitResult& temporary() const {
119 return *temporary_;
120 }
121 bool IsHeapReference() const { return heap_reference_.has_value(); }
124 return *heap_reference_;
125 }
130 bool IsHeapSlice() const { return heap_slice_.has_value(); }
131 const VisitResult& heap_slice() const {
133 return *heap_slice_;
134 }
135 bool IsBitFieldAccess() const {
136 bool is_bitfield_access = bit_field_struct_ != nullptr;
137 DCHECK_EQ(is_bitfield_access, bit_field_.has_value());
138 return is_bitfield_access;
139 }
144 const BitField& bit_field() const {
146 return *bit_field_;
147 }
148
149 std::optional<const Type*> ReferencedType() const {
150 if (IsHeapReference()) {
152 }
153 if (IsHeapSlice()) {
154 if (auto type = Type::MatchUnaryGeneric(
156 return *type;
157 }
160 }
161 if (IsBitFieldAccess()) {
162 return bit_field_->name_and_type.type;
163 }
164 if (IsVariableAccess() || IsHeapSlice() || IsTemporary()) {
165 return GetVisitResult().type();
166 }
167 return std::nullopt;
168 }
169
171 if (IsVariableAccess()) return variable();
172 if (IsHeapSlice()) return heap_slice();
174 return temporary();
175 }
176
177 // For error reporting.
178 const std::string& temporary_description() const {
181 }
182
183 bool IsCallAccess() const {
184 bool is_call_access = eval_function_.has_value();
185 DCHECK_EQ(is_call_access, assign_function_.has_value());
186 return is_call_access;
187 }
190 return call_arguments_;
191 }
192 const std::string& eval_function() const {
194 return *eval_function_;
195 }
196 const std::string& assign_function() const {
198 return *assign_function_;
199 }
200 std::optional<Binding<LocalValue>*> binding() const {
202 return binding_;
203 }
204
205 private:
206 std::optional<VisitResult> variable_;
207 std::optional<VisitResult> temporary_;
208 std::optional<std::string> temporary_description_;
209 std::optional<VisitResult> heap_reference_;
212 std::optional<VisitResult> heap_slice_;
213 std::optional<std::string> eval_function_;
214 std::optional<std::string> assign_function_;
216 std::optional<Binding<LocalValue>*> binding_;
217
218 // The location of the bitfield struct that contains this bitfield, if this
219 // reference is a bitfield access. Uses a shared_ptr so that LocationReference
220 // is copyable, allowing us to set this field equal to a copy of a
221 // stack-allocated LocationReference.
222 std::shared_ptr<const LocationReference> bit_field_struct_;
223 std::optional<BitField> bit_field_;
224
225 LocationReference() = default;
226};
227
229 std::vector<Identifier*> names;
230 std::map<std::string, VisitResult> field_value_map;
231};
232
234 std::map<std::string, VisitResult> array_lengths;
235 std::map<std::string, VisitResult> offsets;
237};
238
239extern uint64_t next_unique_binding_index;
240
241template <class T>
242class Binding;
243
244template <class T>
246 public:
247 std::optional<Binding<T>*> TryLookup(const std::string& name) {
248 if (StartsWithSingleUnderscore(name)) {
249 Error("Trying to reference '", name, "' which is marked as unused.")
250 .Throw();
251 }
252 auto binding = current_bindings_[name];
253 if (binding) {
254 (*binding)->SetUsed();
255 }
256 return binding;
257 }
258
259 private:
260 friend class Binding<T>;
261 std::unordered_map<std::string, std::optional<Binding<T>*>> current_bindings_;
262};
263
264template <class T>
265class Binding : public T {
266 public:
267 template <class... Args>
268 Binding(BindingsManager<T>* manager, const std::string& name, Args&&... args)
269 : T(std::forward<Args>(args)...),
270 manager_(manager),
271 name_(name),
272 previous_binding_(this),
273 used_(false),
274 written_(false),
276 std::swap(previous_binding_, manager_->current_bindings_[name]);
277 }
278 template <class... Args>
279 Binding(BindingsManager<T>* manager, const Identifier* name, Args&&... args)
280 : Binding(manager, name->value, std::forward<Args>(args)...) {
281 declaration_position_ = name->pos;
282 }
284 if (!used_ && !SkipLintCheck()) {
286 "' is never used. Prefix with '_' if this is intentional.")
288 }
289
290 if (CheckWritten() && !written_ && !SkipLintCheck()) {
292 "' is never assigned to. Use 'const' instead of 'let'.")
294 }
295
296 manager_->current_bindings_[name_] = previous_binding_;
297 }
298 Binding(const Binding&) = delete;
299 Binding& operator=(const Binding&) = delete;
300
301 std::string BindingTypeString() const;
302 bool CheckWritten() const;
303
304 const std::string& name() const { return name_; }
306
307 bool Used() const { return used_; }
308 void SetUsed() { used_ = true; }
309
310 bool Written() const { return written_; }
311 void SetWritten() { written_ = true; }
312
313 uint64_t unique_index() const { return unique_index_; }
314
315 private:
316 bool SkipLintCheck() const { return name_.length() > 0 && name_[0] == '_'; }
317
319 const std::string name_;
320 std::optional<Binding*> previous_binding_;
321 SourcePosition declaration_position_ = CurrentSourcePosition::Get();
322 bool used_;
325};
326
327template <class T>
329 public:
330 explicit BlockBindings(BindingsManager<T>* manager) : manager_(manager) {}
331 Binding<T>* Add(std::string name, T value, bool mark_as_used = false) {
333 auto binding =
334 std::make_unique<Binding<T>>(manager_, name, std::move(value));
335 Binding<T>* result = binding.get();
336 if (mark_as_used) binding->SetUsed();
337 bindings_.push_back(std::move(binding));
338 return result;
339 }
340
341 Binding<T>* Add(const Identifier* name, T value, bool mark_as_used = false) {
342 ReportErrorIfAlreadyBound(name->value);
343 auto binding =
344 std::make_unique<Binding<T>>(manager_, name, std::move(value));
345 Binding<T>* result = binding.get();
346 if (mark_as_used) binding->SetUsed();
347 bindings_.push_back(std::move(binding));
348 return result;
349 }
350
351 std::vector<Binding<T>*> bindings() const {
352 std::vector<Binding<T>*> result;
353 result.reserve(bindings_.size());
354 for (auto& b : bindings_) {
355 result.push_back(b.get());
356 }
357 return result;
358 }
359
360 private:
361 void ReportErrorIfAlreadyBound(const std::string& name) {
362 for (const auto& binding : bindings_) {
363 if (binding->name() == name) {
365 "redeclaration of name \"", name,
366 "\" in the same block is illegal, previous declaration at: ",
367 binding->declaration_position());
368 }
369 }
370 }
371
373 std::vector<std::unique_ptr<Binding<T>>> bindings_;
374};
375
377 public:
378 explicit LocalValue(LocationReference reference)
379 : value(std::move(reference)) {}
382 explicit LocalValue(std::function<LocationReference()> lazy)
383 : lazy(std::move(lazy)) {}
384
386 if (value) {
387 const LocationReference& ref = *value;
388 if (ref.IsVariableAccess()) {
389 // Attach the binding to enable the never-assigned-to lint check.
391 }
392 return ref;
393 } else if (lazy) {
394 return (*lazy)();
395 } else {
396 Error("Cannot access ", binding->name(), ": ", inaccessible_explanation)
397 .Throw();
398 }
399 }
400
401 bool IsAccessibleNonLazy() const { return value.has_value(); }
402
403 private:
404 std::optional<LocationReference> value;
405 std::optional<std::function<LocationReference()>> lazy;
407};
408
411 std::vector<const Type*> parameter_types;
412
413 explicit LocalLabel(Block* block,
414 std::vector<const Type*> parameter_types = {})
415 : block(block), parameter_types(std::move(parameter_types)) {}
416};
417
418template <>
419inline std::string Binding<LocalValue>::BindingTypeString() const {
420 return "Variable ";
421}
422template <>
424 // Do the check only for non-const variables and non struct types.
425 auto binding = *manager_->current_bindings_[name_];
426 if (!binding->IsAccessibleNonLazy()) return false;
427 const LocationReference& ref = binding->GetLocationReference(binding);
428 if (!ref.IsVariableAccess()) return false;
429 return !ref.GetVisitResult().type()->StructSupertype();
430}
431template <>
432inline std::string Binding<LocalLabel>::BindingTypeString() const {
433 return "Label ";
434}
435template <>
437 return false;
438}
439
440struct Arguments {
442 std::vector<Binding<LocalLabel>*> labels;
443};
444
445// Determine if a callable should be considered as an overload.
446bool IsCompatibleSignature(const Signature& sig, const TypeVector& types,
447 size_t label_count);
448
450 public:
452 const std::string& output_directory);
453 void GenerateVisitorLists(const std::string& output_directory);
454 void GenerateBitFields(const std::string& output_directory);
455 void GeneratePrintDefinitions(const std::string& output_directory);
456 void GenerateClassDefinitions(const std::string& output_directory);
457 void GenerateBodyDescriptors(const std::string& output_directory);
458 void GenerateInstanceTypes(const std::string& output_directory);
459 void GenerateClassVerifiers(const std::string& output_directory);
460 void GenerateEnumVerifiers(const std::string& output_directory);
461 void GenerateClassDebugReaders(const std::string& output_directory);
462 void GenerateExportedMacrosAssembler(const std::string& output_directory);
463 void GenerateCSATypes(const std::string& output_directory);
464
466 const Type* Visit(Statement* stmt);
467
468 template <typename T>
470 const std::string& aggregate_name, const std::vector<T>& aggregate_fields,
471 const std::vector<NameAndExpression>& initializers,
472 bool ignore_first_field = false) {
473 size_t fields_offset = ignore_first_field ? 1 : 0;
474 size_t fields_size = aggregate_fields.size() - fields_offset;
475 for (size_t i = 0; i < std::min(fields_size, initializers.size()); i++) {
476 const std::string& field_name =
477 aggregate_fields[i + fields_offset].name_and_type.name;
478 Identifier* found_name = initializers[i].name;
479 if (field_name != found_name->value) {
480 Error("Expected field name \"", field_name, "\" instead of \"",
481 found_name->value, "\"")
482 .Position(found_name->pos)
483 .Throw();
484 }
485 }
486 if (fields_size != initializers.size()) {
487 ReportError("expected ", fields_size, " initializers for ",
488 aggregate_name, " found ", initializers.size());
489 }
490 }
491
493 const ClassType* class_type,
494 const std::vector<NameAndExpression>& expressions);
496 VisitResult object, const Field& field, const ClassType* class_type,
497 bool treat_optional_as_indexed = false);
499 VisitResult object, const Field& field,
500 const LayoutForInitialization& layout);
502 Expression* array_length, Namespace* nspace,
503 const std::map<std::string, LocalValue>& bindings);
504 VisitResult GenerateArrayLength(VisitResult object, const Field& field);
505 VisitResult GenerateArrayLength(const ClassType* class_type,
506 const InitializerResults& initializer_results,
507 const Field& field);
509 const ClassType* class_type,
510 const InitializerResults& initializer_results);
511
512 void InitializeClass(const ClassType* class_type, VisitResult allocate_result,
513 const InitializerResults& initializer_results,
514 const LayoutForInitialization& layout);
515
517
519 LocationReference LookupLocalValue(const std::string& name);
524 LocationReference reference, const std::string& fieldname,
525 bool ignore_stuct_field_constness = false,
526 std::optional<SourcePosition> pos = {});
529 VisitResult index);
530
532
534
537
538 void VisitAllDeclarables();
539 void Visit(Declarable* delarable, std::optional<SourceId> file = {});
540 void Visit(TypeAlias* decl);
541 VisitResult InlineMacro(Macro* macro,
542 std::optional<LocationReference> this_reference,
543 const std::vector<VisitResult>& arguments,
544 const std::vector<Block*> label_blocks);
545 void VisitMacroCommon(Macro* macro);
546 void Visit(ExternMacro* macro) {}
547 void Visit(TorqueMacro* macro);
548 void Visit(Method* macro);
549 void Visit(Builtin* builtin);
550 void Visit(NamespaceConstant* decl);
551
552 VisitResult Visit(CallExpression* expr, bool is_tail = false);
555 const Type* Visit(TailCallStatement* stmt);
556
558
561
572
573 const Type* Visit(ReturnStatement* stmt);
574 const Type* Visit(GotoStatement* stmt);
575 const Type* Visit(IfStatement* stmt);
576 const Type* Visit(WhileStatement* stmt);
577 const Type* Visit(BreakStatement* stmt);
578 const Type* Visit(ContinueStatement* stmt);
579 const Type* Visit(ForLoopStatement* stmt);
580 const Type* Visit(VarDeclarationStatement* stmt);
582 BlockBindings<LocalValue>* block_bindings);
583 const Type* Visit(BlockStatement* block);
584 const Type* Visit(ExpressionStatement* stmt);
585 const Type* Visit(DebugStatement* stmt);
586 const Type* Visit(AssertStatement* stmt);
587
588 void BeginGeneratedFiles();
589 void EndGeneratedFiles();
591 void EndDebugMacrosFile();
592
593 void GenerateImplementation(const std::string& dir);
594
595 DECLARE_CONTEXTUAL_VARIABLE(ValueBindingsManager,
597 DECLARE_CONTEXTUAL_VARIABLE(LabelBindingsManager,
600 DECLARE_CONTEXTUAL_VARIABLE(CurrentFileStreams,
602 DECLARE_CONTEXTUAL_VARIABLE(CurrentReturnValue, std::optional<VisitResult>);
603
604 // A BindingsManagersScope has to be active for local bindings to be created.
605 // Shadowing an existing BindingsManagersScope by creating a new one hides all
606 // existing bindings while the additional BindingsManagersScope is active.
608 ValueBindingsManager::Scope value_bindings_manager;
609 LabelBindingsManager::Scope label_bindings_manager;
610 };
611
612 void SetDryRun(bool is_dry_run) { is_dry_run_ = is_dry_run; }
613
614 private:
615 std::optional<Block*> GetCatchBlock();
616 void GenerateCatchBlock(std::optional<Block*> catch_block);
617
618 // {StackScope} records the stack height at creation time and reconstructs it
619 // when being destructed by emitting a {DeleteRangeInstruction}, except for
620 // the slots protected by {StackScope::Yield}. Calling {Yield(v)} deletes all
621 // slots above the initial stack height except for the slots of {v}, which are
622 // moved to form the only slots above the initial height and marks them to
623 // survive destruction of the {StackScope}. A typical pattern is the
624 // following:
625 //
626 // VisitResult result;
627 // {
628 // StackScope stack_scope(this);
629 // // ... create temporary slots ...
630 // result = stack_scope.Yield(surviving_slots);
631 // }
633 public:
634 explicit StackScope(ImplementationVisitor* visitor) : visitor_(visitor) {
635 base_ = visitor_->assembler().CurrentStack().AboveTop();
636 }
638 DCHECK(!closed_);
639 closed_ = true;
640 if (!result.IsOnStack()) {
641 if (!visitor_->assembler().CurrentBlockIsComplete()) {
642 visitor_->assembler().DropTo(base_);
643 }
644 return result;
645 }
646 DCHECK_LE(base_, result.stack_range().begin());
647 DCHECK_LE(result.stack_range().end(),
648 visitor_->assembler().CurrentStack().AboveTop());
649 visitor_->assembler().DropTo(result.stack_range().end());
650 visitor_->assembler().DeleteRange(
651 StackRange{base_, result.stack_range().begin()});
652 base_ = visitor_->assembler().CurrentStack().AboveTop();
653 return VisitResult(result.type(), visitor_->assembler().TopRange(
654 result.stack_range().Size()));
655 }
656
657 void Close() {
658 DCHECK(!closed_);
659 closed_ = true;
660 if (!visitor_->assembler().CurrentBlockIsComplete()) {
661 visitor_->assembler().DropTo(base_);
662 }
663 }
664
666 if (closed_) {
668 !visitor_->assembler().CurrentBlockIsComplete(),
669 base_ == visitor_->assembler().CurrentStack().AboveTop());
670 } else {
671 Close();
672 }
673 }
674
675 private:
678 bool closed_ = false;
679 };
680
682 public:
683 BreakContinueActivator(Block* break_block, Block* continue_block)
684 : break_binding_{&LabelBindingsManager::Get(), kBreakLabelName,
685 LocalLabel{break_block}},
686 continue_binding_{&LabelBindingsManager::Get(), kContinueLabelName,
687 LocalLabel{continue_block}} {}
688
689 private:
692 };
693
694 std::optional<Binding<LocalValue>*> TryLookupLocalValue(
695 const std::string& name);
696 std::optional<Binding<LocalLabel>*> TryLookupLabel(const std::string& name);
697 Binding<LocalLabel>* LookupLabel(const std::string& name);
698 Block* LookupSimpleLabel(const std::string& name);
699 template <class Container>
701 const Container& declaration_container,
702 const TypeVector& types,
703 const std::vector<Binding<LocalLabel>*>& labels,
704 const TypeVector& specialization_types,
705 bool silence_errors = false);
706 bool TestLookupCallable(const QualifiedName& name,
707 const TypeVector& parameter_types);
708
709 template <class Container>
711 const Container& declaration_container,
712 const Arguments& arguments,
713 const TypeVector& specialization_types);
714
715 Method* LookupMethod(const std::string& name,
716 const AggregateType* receiver_type,
717 const Arguments& arguments,
718 const TypeVector& specialization_types);
719
721 GenericCallable* generic, const TypeVector& explicit_specialization_types,
722 const TypeVector& explicit_arguments);
723
724 const Type* GetCommonType(const Type* left, const Type* right);
725
726 VisitResult GenerateCopy(const VisitResult& to_copy);
727
728 void GenerateAssignToLocation(const LocationReference& reference,
729 const VisitResult& assignment_value);
730
731 void AddCallParameter(Callable* callable, VisitResult parameter,
732 const Type* parameter_type,
733 std::vector<VisitResult>* converted_arguments,
734 StackRange* argument_range,
735 std::vector<std::string>* constexpr_arguments,
736 bool inline_macro);
737
739 std::optional<LocationReference> this_parameter,
740 Arguments parameters,
741 const TypeVector& specialization_types = {},
742 bool tail_call = false);
743 VisitResult GenerateCall(const QualifiedName& callable_name,
744 Arguments parameters,
745 const TypeVector& specialization_types = {},
746 bool tail_call = false);
747 VisitResult GenerateCall(std::string callable_name, Arguments parameters,
748 const TypeVector& specialization_types = {},
749 bool tail_call = false) {
750 return GenerateCall(QualifiedName(std::move(callable_name)),
751 std::move(parameters), specialization_types, tail_call);
752 }
753 VisitResult GeneratePointerCall(Expression* callee,
754 const Arguments& parameters, bool tail_call);
755
756 void GenerateBranch(const VisitResult& condition, Block* true_block,
757 Block* false_block);
758
759 VisitResult GenerateBoolConstant(bool constant);
760
761 void GenerateExpressionBranch(Expression* expression, Block* true_block,
762 Block* false_block);
763
764 cpp::Function GenerateMacroFunctionDeclaration(Macro* macro);
765
766 cpp::Function GenerateFunction(
767 cpp::Class* owner, const std::string& name, const Signature& signature,
768 const NameVector& parameter_names, bool pass_code_assembler_state = true,
769 std::vector<std::string>* generated_parameter_names = nullptr);
770
771 VisitResult GenerateImplicitConvert(const Type* destination_type,
772 VisitResult source);
773
774 StackRange GenerateLabelGoto(LocalLabel* label,
775 std::optional<StackRange> arguments = {});
776
777 VisitResult GenerateSetBitField(const Type* bitfield_struct_type,
778 const BitField& bitfield,
779 VisitResult bitfield_struct,
780 VisitResult value,
781 bool starts_as_zero = false);
782
783 std::vector<Binding<LocalLabel>*> LabelsFromIdentifiers(
784 const std::vector<Identifier*>& names);
785
786 StackRange LowerParameter(const Type* type, const std::string& parameter_name,
787 Stack<std::string>* lowered_parameters);
788
789 void LowerLabelParameter(const Type* type, const std::string& parameter_name,
790 std::vector<std::string>* lowered_parameters);
791
792 std::string ExternalLabelName(const std::string& label_name);
793 std::string ExternalLabelParameterName(const std::string& label_name,
794 size_t i);
795 std::string ExternalParameterName(const std::string& name);
796
797 std::ostream& csa_ccfile() {
798 if (auto* streams = CurrentFileStreams::Get()) {
799 switch (output_type_) {
800 case OutputType::kCSA:
801 return streams->csa_ccfile;
802 case OutputType::kCC:
803 return streams->class_definition_inline_headerfile_macro_definitions;
805 return debug_macros_cc_;
806 default:
807 UNREACHABLE();
808 }
809 }
810 return null_stream_;
811 }
812 std::ostream& csa_headerfile() {
813 if (auto* streams = CurrentFileStreams::Get()) {
814 switch (output_type_) {
815 case OutputType::kCSA:
816 return streams->csa_headerfile;
817 case OutputType::kCC:
818 return streams->class_definition_inline_headerfile_macro_declarations;
820 return debug_macros_h_;
821 default:
822 UNREACHABLE();
823 }
824 }
825 return null_stream_;
826 }
827
829
830 void SetReturnValue(VisitResult return_value) {
831 std::optional<VisitResult>& current_return_value =
832 CurrentReturnValue::Get();
833 DCHECK_IMPLIES(current_return_value, *current_return_value == return_value);
834 current_return_value = std::move(return_value);
835 }
836
838 VisitResult return_value = *CurrentReturnValue::Get();
839 CurrentReturnValue::Get() = std::nullopt;
840 return return_value;
841 }
842
843 void WriteFile(const std::string& file, const std::string& content) {
844 if (is_dry_run_) return;
845 ReplaceFileContentsIfDifferent(file, content);
846 }
847
849 const Expression* expr) const {
850 auto it = bitfield_expressions_.find(expr);
851 if (it == bitfield_expressions_.end()) return nullptr;
852 return it->second;
853 }
854
855 void PropagateBitfieldMark(const Expression* original,
856 const Expression* derived) {
857 if (const Identifier* source =
859 bitfield_expressions_[derived] = source;
860 }
861 }
862
863 class MacroInliningScope;
864
865 std::optional<CfgAssembler> assembler_;
868
869 // Just for allowing us to emit warnings. After visiting an Expression, if
870 // that Expression is a bitfield load, plus an optional inversion or an
871 // equality check with a constant, then that Expression will be present in
872 // this map. The Identifier associated is the bitfield struct that contains
873 // the value to load.
874 std::unordered_map<const Expression*, const Identifier*>
876
877 // For emitting warnings. Contains the current set of macros being inlined in
878 // calls to InlineMacro.
879 std::unordered_set<const Macro*> inlining_macros_;
880
881 // The contents of the debug macros output files. These contain all Torque
882 // macros that have been generated using the C++ backend with debug purpose.
883 std::stringstream debug_macros_cc_;
884 std::stringstream debug_macros_h_;
885
887};
888
890
891} // namespace v8::internal::torque
892
893#endif // V8_TORQUE_IMPLEMENTATION_VISITOR_H_
SourcePosition pos
Binding(BindingsManager< T > *manager, const std::string &name, Args &&... args)
Binding(const Binding &)=delete
std::string BindingTypeString() const
Binding(BindingsManager< T > *manager, const Identifier *name, Args &&... args)
Binding & operator=(const Binding &)=delete
const std::string & name() const
std::optional< Binding * > previous_binding_
SourcePosition declaration_position() const
std::unordered_map< std::string, std::optional< Binding< T > * > > current_bindings_
std::optional< Binding< T > * > TryLookup(const std::string &name)
Binding< T > * Add(const Identifier *name, T value, bool mark_as_used=false)
std::vector< std::unique_ptr< Binding< T > > > bindings_
std::vector< Binding< T > * > bindings() const
Binding< T > * Add(std::string name, T value, bool mark_as_used=false)
BlockBindings(BindingsManager< T > *manager)
void ReportErrorIfAlreadyBound(const std::string &name)
VisitResult GenerateCopy(const VisitResult &to_copy)
DECLARE_CONTEXTUAL_VARIABLE(LabelBindingsManager, BindingsManager< LocalLabel >)
void GenerateClassDebugReaders(const std::string &output_directory)
void GeneratePrintDefinitions(const std::string &output_directory)
std::unordered_set< const Macro * > inlining_macros_
void GenerateBodyDescriptors(const std::string &output_directory)
VisitResult GenerateFetchFromLocation(const LocationReference &reference)
LocationReference GenerateFieldAccess(LocationReference reference, const std::string &fieldname, bool ignore_stuct_field_constness=false, std::optional< SourcePosition > pos={})
std::vector< Binding< LocalLabel > * > LabelsFromIdentifiers(const std::vector< Identifier * > &names)
void AddCallParameter(Callable *callable, VisitResult parameter, const Type *parameter_type, std::vector< VisitResult > *converted_arguments, StackRange *argument_range, std::vector< std::string > *constexpr_arguments, bool inline_macro)
void GenerateAssignToLocation(const LocationReference &reference, const VisitResult &assignment_value)
void LowerLabelParameter(const Type *type, const std::string &parameter_name, std::vector< std::string > *lowered_parameters)
cpp::Function GenerateFunction(cpp::Class *owner, const std::string &name, const Signature &signature, const NameVector &parameter_names, bool pass_code_assembler_state=true, std::vector< std::string > *generated_parameter_names=nullptr)
void GenerateVisitorLists(const std::string &output_directory)
void GenerateBuiltinDefinitionsAndInterfaceDescriptors(const std::string &output_directory)
VisitResult GenerateSetBitField(const Type *bitfield_struct_type, const BitField &bitfield, VisitResult bitfield_struct, VisitResult value, bool starts_as_zero=false)
void GenerateBranch(const VisitResult &condition, Block *true_block, Block *false_block)
std::string ExternalLabelParameterName(const std::string &label_name, size_t i)
Binding< LocalLabel > * LookupLabel(const std::string &name)
InitializerResults VisitInitializerResults(const ClassType *class_type, const std::vector< NameAndExpression > &expressions)
LocationReference GenerateFieldReference(VisitResult object, const Field &field, const ClassType *class_type, bool treat_optional_as_indexed=false)
void GenerateCSATypes(const std::string &output_directory)
Method * LookupMethod(const std::string &name, const AggregateType *receiver_type, const Arguments &arguments, const TypeVector &specialization_types)
VisitResult GenerateCall(Callable *callable, std::optional< LocationReference > this_parameter, Arguments parameters, const TypeVector &specialization_types={}, bool tail_call=false)
void GenerateClassVerifiers(const std::string &output_directory)
void GenerateInstanceTypes(const std::string &output_directory)
VisitResult GenerateCall(std::string callable_name, Arguments parameters, const TypeVector &specialization_types={}, bool tail_call=false)
void GenerateCatchBlock(std::optional< Block * > catch_block)
void GenerateEnumVerifiers(const std::string &output_directory)
LocationReference GenerateReferenceToItemInHeapSlice(LocationReference slice, VisitResult index)
bool TestLookupCallable(const QualifiedName &name, const TypeVector &parameter_types)
DECLARE_CONTEXTUAL_VARIABLE(CurrentFileStreams, GlobalContext::PerFileStreams *)
void CheckInitializersWellformed(const std::string &aggregate_name, const std::vector< T > &aggregate_fields, const std::vector< NameAndExpression > &initializers, bool ignore_first_field=false)
std::string ExternalParameterName(const std::string &name)
const Identifier * TryGetSourceForBitfieldExpression(const Expression *expr) const
void GenerateClassDefinitions(const std::string &output_directory)
LayoutForInitialization GenerateLayoutForInitialization(const ClassType *class_type, const InitializerResults &initializer_results)
DECLARE_CONTEXTUAL_VARIABLE(ValueBindingsManager, BindingsManager< LocalValue >)
VisitResult InlineMacro(Macro *macro, std::optional< LocationReference > this_reference, const std::vector< VisitResult > &arguments, const std::vector< Block * > label_blocks)
LocationReference GetLocationReference(Expression *location)
void GenerateBitFields(const std::string &output_directory)
VisitResult GenerateArrayLength(Expression *array_length, Namespace *nspace, const std::map< std::string, LocalValue > &bindings)
DECLARE_CONTEXTUAL_VARIABLE(CurrentCallable, Callable *)
TypeArgumentInference InferSpecializationTypes(GenericCallable *generic, const TypeVector &explicit_specialization_types, const TypeVector &explicit_arguments)
LocationReference LookupLocalValue(const std::string &name)
StackRange LowerParameter(const Type *type, const std::string &parameter_name, Stack< std::string > *lowered_parameters)
StackRange GenerateLabelGoto(LocalLabel *label, std::optional< StackRange > arguments={})
DECLARE_CONTEXTUAL_VARIABLE(CurrentReturnValue, std::optional< VisitResult >)
Callable * LookupCallable(const QualifiedName &name, const Container &declaration_container, const TypeVector &types, const std::vector< Binding< LocalLabel > * > &labels, const TypeVector &specialization_types, bool silence_errors=false)
VisitResult GenerateImplicitConvert(const Type *destination_type, VisitResult source)
const Type * GetCommonType(const Type *left, const Type *right)
std::string ExternalLabelName(const std::string &label_name)
void InitializeClass(const ClassType *class_type, VisitResult allocate_result, const InitializerResults &initializer_results, const LayoutForInitialization &layout)
void GenerateExpressionBranch(Expression *expression, Block *true_block, Block *false_block)
std::optional< Binding< LocalLabel > * > TryLookupLabel(const std::string &name)
void GenerateExportedMacrosAssembler(const std::string &output_directory)
VisitResult GeneratePointerCall(Expression *callee, const Arguments &parameters, bool tail_call)
std::unordered_map< const Expression *, const Identifier * > bitfield_expressions_
void PropagateBitfieldMark(const Expression *original, const Expression *derived)
void WriteFile(const std::string &file, const std::string &content)
std::optional< Binding< LocalValue > * > TryLookupLocalValue(const std::string &name)
LocationReference GenerateFieldReferenceForInit(VisitResult object, const Field &field, const LayoutForInitialization &layout)
LocalValue(std::function< LocationReference()> lazy)
LocalValue(std::string inaccessible_explanation)
LocalValue(LocationReference reference)
LocationReference GetLocationReference(Binding< LocalValue > *binding)
std::optional< LocationReference > value
std::optional< std::function< LocationReference()> > lazy
std::optional< std::string > temporary_description_
std::shared_ptr< const LocationReference > bit_field_struct_
static LocationReference FieldAccess(VisitResult object, std::string fieldname)
std::optional< Binding< LocalValue > * > binding_
FieldSynchronization heap_reference_synchronization() const
const LocationReference & bit_field_struct_location() const
static LocationReference HeapReference(VisitResult heap_reference, FieldSynchronization synchronization=FieldSynchronization::kNone)
static LocationReference Temporary(VisitResult temporary, std::string description)
static LocationReference HeapSlice(VisitResult heap_slice)
static LocationReference VariableAccess(VisitResult variable, std::optional< Binding< LocalValue > * > binding=std::nullopt)
const VisitResultVector & call_arguments() const
static LocationReference ArrayAccess(VisitResult base, VisitResult offset)
const std::string & temporary_description() const
std::optional< const Type * > ReferencedType() const
static LocationReference BitFieldAccess(const LocationReference &object, BitField field)
std::optional< Binding< LocalValue > * > binding() const
MessageBuilder & Position(SourcePosition position)
Definition utils.h:52
static GenericType * GetConstSliceGeneric()
static std::optional< const Type * > MatchReferenceGeneric(const Type *reference_type, bool *is_const=nullptr)
static GenericType * GetMutableSliceGeneric()
static std::optional< const Type * > MatchUnaryGeneric(const Type *type, GenericType *generic)
Definition types.cc:573
base::Vector< const DirectHandle< Object > > args
Definition execution.cc:74
Label label
int32_t offset
ZoneVector< RpoNumber > & result
const char * name_
InstructionOperand source
STL namespace.
V8_INLINE const Operation & Get(const Graph &graph, OpIndex index)
Definition graph.h:1231
static constexpr const char * kContinueLabelName
void ReportError(Args &&... args)
Definition utils.h:96
void ReplaceFileContentsIfDifferent(const std::string &file_path, const std::string &contents)
Definition utils.cc:327
MessageBuilder Lint(Args &&... args)
Definition utils.h:85
std::vector< Identifier * > NameVector
Definition types.h:906
static constexpr const char * kBreakLabelName
bool StartsWithSingleUnderscore(const std::string &str)
Definition utils.cc:323
std::vector< const Type * > TypeVector
Definition types.h:85
MessageBuilder Error(Args &&... args)
Definition utils.h:81
bool IsCompatibleSignature(const Signature &sig, const TypeVector &types, size_t label_count)
too high values may cause the compiler to set high thresholds for inlining to as much as possible avoid inlined allocation of objects that cannot escape trace load stores from virtual maglev objects use TurboFan fast string builder analyze liveness of environment slots and zap dead values trace TurboFan load elimination emit data about basic block usage in builtins to this enable builtin reordering when run mksnapshot flag for emit warnings when applying builtin profile data verify register allocation in TurboFan randomly schedule instructions to stress dependency tracking enable store store elimination in TurboFan rewrite far to near simulate GC compiler thread race related to allow float parameters to be passed in simulator mode JS Wasm Run additional turbo_optimize_inlined_js_wasm_wrappers enable experimental feedback collection in generic lowering enable Turboshaft s WasmLoadElimination enable Turboshaft s low level load elimination for JS enable Turboshaft s escape analysis for string concatenation use enable Turbolev features that we want to ship in the not too far future trace individual Turboshaft reduction steps trace intermediate Turboshaft reduction steps invocation count threshold for early optimization Enables optimizations which favor memory size over execution speed Enables sampling allocation profiler with X as a sample interval min size of a semi the new space consists of two semi spaces max size of the Collect garbage after Collect garbage after keeps maps alive for< n > old space garbage collections print one detailed trace line in name
Definition flags.cc:2086
kWasmInternalFunctionIndirectPointerTag kProtectedInstanceDataOffset sig
#define DCHECK_LE(v1, v2)
Definition logging.h:490
#define CHECK(condition)
Definition logging.h:124
#define DCHECK_IMPLIES(v1, v2)
Definition logging.h:493
#define DCHECK(condition)
Definition logging.h:482
#define DCHECK_EQ(v1, v2)
Definition logging.h:485
std::vector< Binding< LocalLabel > * > labels
SourcePosition pos
Definition ast.h:112
std::map< std::string, VisitResult > field_value_map
std::map< std::string, VisitResult > offsets
std::map< std::string, VisitResult > array_lengths
LocalLabel(Block *block, std::vector< const Type * > parameter_types={})
std::vector< const Type * > parameter_types
RootVisitor * visitor_
#define V8_NODISCARD
Definition v8config.h:693
wasm::ValueType type