summaryrefslogtreecommitdiff
path: root/deps/v8/src/torque/implementation-visitor.h
diff options
context:
space:
mode:
Diffstat (limited to 'deps/v8/src/torque/implementation-visitor.h')
-rw-r--r--deps/v8/src/torque/implementation-visitor.h258
1 files changed, 169 insertions, 89 deletions
diff --git a/deps/v8/src/torque/implementation-visitor.h b/deps/v8/src/torque/implementation-visitor.h
index 43520239da..a7440251d7 100644
--- a/deps/v8/src/torque/implementation-visitor.h
+++ b/deps/v8/src/torque/implementation-visitor.h
@@ -9,6 +9,7 @@
#include "src/base/macros.h"
#include "src/torque/ast.h"
+#include "src/torque/cfg.h"
#include "src/torque/file-visitor.h"
#include "src/torque/global-context.h"
#include "src/torque/types.h"
@@ -18,18 +19,95 @@ namespace v8 {
namespace internal {
namespace torque {
-struct LocationReference {
- LocationReference(Value* value, VisitResult base, VisitResult index)
- : value(value), base(base), index(index) {}
- Value* value;
- VisitResult base;
- VisitResult index;
+// LocationReference is the representation of an l-value, so a value that might
+// allow for assignment. For uniformity, this class can also represent
+// unassignable temporaries. Assignable values fall in two categories:
+// - stack ranges that represent mutable variables, including structs.
+// - field or element access expressions that generate operator calls.
+class LocationReference {
+ public:
+ // An assignable stack range.
+ static LocationReference VariableAccess(VisitResult variable) {
+ DCHECK(variable.IsOnStack());
+ LocationReference result;
+ result.variable_ = std::move(variable);
+ return result;
+ }
+ // An unassignable value. {description} is only used for error messages.
+ static LocationReference Temporary(VisitResult temporary,
+ std::string description) {
+ LocationReference result;
+ result.temporary_ = std::move(temporary);
+ result.temporary_description_ = std::move(description);
+ return result;
+ }
+ static LocationReference ArrayAccess(VisitResult base, VisitResult offset) {
+ LocationReference result;
+ result.eval_function_ = std::string{"[]"};
+ result.assign_function_ = std::string{"[]="};
+ result.call_arguments_ = {base, offset};
+ return result;
+ }
+ static LocationReference FieldAccess(VisitResult object,
+ std::string fieldname) {
+ LocationReference result;
+ result.eval_function_ = "." + fieldname;
+ result.assign_function_ = "." + fieldname + "=";
+ result.call_arguments_ = {object};
+ return result;
+ }
+
+ bool IsConst() const { return temporary_.has_value(); }
+
+ bool IsVariableAccess() const { return variable_.has_value(); }
+ const VisitResult& variable() const {
+ DCHECK(IsVariableAccess());
+ return *variable_;
+ }
+ bool IsTemporary() const { return temporary_.has_value(); }
+ const VisitResult& temporary() const {
+ DCHECK(IsTemporary());
+ return *temporary_;
+ }
+ // For error reporting.
+ const std::string& temporary_description() const {
+ DCHECK(IsTemporary());
+ return *temporary_description_;
+ }
+
+ bool IsCallAccess() const {
+ bool is_call_access = eval_function_.has_value();
+ DCHECK_EQ(is_call_access, assign_function_.has_value());
+ return is_call_access;
+ }
+ const VisitResultVector& call_arguments() const {
+ DCHECK(IsCallAccess());
+ return call_arguments_;
+ }
+ const std::string& eval_function() const {
+ DCHECK(IsCallAccess());
+ return *eval_function_;
+ }
+ const std::string& assign_function() const {
+ DCHECK(IsCallAccess());
+ return *assign_function_;
+ }
+
+ private:
+ base::Optional<VisitResult> variable_;
+ base::Optional<VisitResult> temporary_;
+ base::Optional<std::string> temporary_description_;
+ base::Optional<std::string> eval_function_;
+ base::Optional<std::string> assign_function_;
+ VisitResultVector call_arguments_;
+
+ LocationReference() = default;
};
class ImplementationVisitor : public FileVisitor {
public:
explicit ImplementationVisitor(GlobalContext& global_context)
- : FileVisitor(global_context), indent_(0), next_temp_(0) {}
+ : FileVisitor(global_context) {}
void Visit(Ast* ast) { Visit(ast->default_module()); }
@@ -39,44 +117,23 @@ class ImplementationVisitor : public FileVisitor {
VisitResult Visit(StructExpression* decl);
- LocationReference GetLocationReference(LocationExpression* location);
- LocationReference GetLocationReference(IdentifierExpression* expr) {
- return LocationReference(declarations()->LookupValue(expr->name), {}, {});
- }
+ LocationReference GetLocationReference(Expression* location);
+ LocationReference GetLocationReference(IdentifierExpression* expr);
LocationReference GetLocationReference(FieldAccessExpression* expr);
- LocationReference GetLocationReference(ElementAccessExpression* expr) {
- return LocationReference({}, Visit(expr->array), Visit(expr->index));
- }
-
- std::string RValueFlattenStructs(VisitResult result);
+ LocationReference GetLocationReference(ElementAccessExpression* expr);
- VisitResult GenerateFetchFromLocation(LocationReference reference) {
- const Value* value = reference.value;
- return VisitResult(value->type(), value);
- }
- VisitResult GenerateFetchFromLocation(LocationExpression* location,
- LocationReference reference);
- VisitResult GenerateFetchFromLocation(IdentifierExpression* expr,
- LocationReference reference) {
- return GenerateFetchFromLocation(reference);
- }
- VisitResult GenerateFetchFromLocation(FieldAccessExpression* expr,
- LocationReference reference);
- VisitResult GenerateFetchFromLocation(ElementAccessExpression* expr,
- LocationReference reference) {
- Arguments arguments;
- arguments.parameters = {reference.base, reference.index};
- return GenerateCall("[]", arguments);
- }
+ VisitResult GenerateFetchFromLocation(const LocationReference& reference);
VisitResult GetBuiltinCode(Builtin* builtin);
VisitResult Visit(IdentifierExpression* expr);
VisitResult Visit(FieldAccessExpression* expr) {
- return GenerateFetchFromLocation(expr, GetLocationReference(expr));
+ StackScope scope(this);
+ return scope.Yield(GenerateFetchFromLocation(GetLocationReference(expr)));
}
VisitResult Visit(ElementAccessExpression* expr) {
- return GenerateFetchFromLocation(expr, GetLocationReference(expr));
+ StackScope scope(this);
+ return scope.Yield(GenerateFetchFromLocation(GetLocationReference(expr)));
}
void Visit(ModuleDeclaration* decl);
@@ -120,8 +177,9 @@ class ImplementationVisitor : public FileVisitor {
VisitResult Visit(StringLiteralExpression* expr);
VisitResult Visit(NumberLiteralExpression* expr);
VisitResult Visit(AssumeTypeImpossibleExpression* expr);
+ VisitResult Visit(TryLabelExpression* expr);
+ VisitResult Visit(StatementExpression* expr);
- const Type* Visit(TryLabelStatement* stmt);
const Type* Visit(ReturnStatement* stmt);
const Type* Visit(GotoStatement* stmt);
const Type* Visit(IfStatement* stmt);
@@ -146,63 +204,70 @@ class ImplementationVisitor : public FileVisitor {
std::string GetDSLAssemblerName(Module* module);
- void GenerateIndent();
-
- class ScopedIndent {
+ // {StackScope} records the stack height at creation time and reconstructs it
+ // when being destructed by emitting a {DeleteRangeInstruction}, except for
+ // the slots protected by {StackScope::Yield}. Calling {Yield(v)} deletes all
+ // slots above the initial stack height except for the slots of {v}, which are
+ // moved to form the only slots above the initial height and marks them to
+ // survive destruction of the {StackScope}. A typical pattern is the
+ // following:
+ //
+ // VisitResult result;
+ // {
+ // StackScope stack_scope(this);
+ // // ... create temporary slots ...
+ // result = stack_scope.Yield(surviving_slots);
+ // }
+ class StackScope {
public:
- explicit ScopedIndent(ImplementationVisitor* visitor, bool new_lines = true)
- : new_lines_(new_lines), visitor_(visitor) {
- if (new_lines) visitor->GenerateIndent();
- visitor->source_out() << "{";
- if (new_lines) visitor->source_out() << "\n";
- visitor->indent_++;
+ explicit StackScope(ImplementationVisitor* visitor) : visitor_(visitor) {
+ base_ = visitor_->assembler().CurrentStack().AboveTop();
+ }
+ VisitResult Yield(VisitResult result) {
+ DCHECK(!yield_called_);
+ yield_called_ = true;
+ if (!result.IsOnStack()) {
+ if (!visitor_->assembler().CurrentBlockIsComplete()) {
+ visitor_->assembler().DropTo(base_);
+ }
+ return result;
+ }
+ DCHECK_LE(base_, result.stack_range().begin());
+ DCHECK_LE(result.stack_range().end(),
+ visitor_->assembler().CurrentStack().AboveTop());
+ visitor_->assembler().DropTo(result.stack_range().end());
+ visitor_->assembler().DeleteRange(
+ StackRange{base_, result.stack_range().begin()});
+ base_ = visitor_->assembler().CurrentStack().AboveTop();
+ return VisitResult(result.type(), visitor_->assembler().TopRange(
+ result.stack_range().Size()));
}
- ~ScopedIndent() {
- visitor_->indent_--;
- visitor_->GenerateIndent();
- visitor_->source_out() << "}";
- if (new_lines_) visitor_->source_out() << "\n";
+
+ ~StackScope() {
+ if (yield_called_) {
+ DCHECK_IMPLIES(
+ !visitor_->assembler().CurrentBlockIsComplete(),
+ base_ == visitor_->assembler().CurrentStack().AboveTop());
+ } else if (!visitor_->assembler().CurrentBlockIsComplete()) {
+ visitor_->assembler().DropTo(base_);
+ }
}
private:
- bool new_lines_;
ImplementationVisitor* visitor_;
+ BottomOffset base_;
+ bool yield_called_ = false;
};
Callable* LookupCall(const std::string& name, const Arguments& arguments,
const TypeVector& specialization_types);
- bool GenerateChangedVarFromControlSplit(const Variable* v, bool first = true);
-
- void GetFlattenedStructsVars(const Variable* base,
- std::set<const Variable*>* vars);
-
- void GenerateChangedVarsFromControlSplit(AstNode* node);
-
const Type* GetCommonType(const Type* left, const Type* right);
VisitResult GenerateCopy(const VisitResult& to_copy);
- void GenerateAssignToVariable(Variable* var, VisitResult value);
-
- void GenerateAssignToLocation(LocationExpression* location,
- const LocationReference& reference,
- VisitResult assignment_value);
-
- void GenerateVariableDeclaration(const Variable* var);
-
- Variable* GeneratePredeclaredVariableDeclaration(
- const std::string& name,
- const base::Optional<VisitResult>& initialization);
-
- Variable* GenerateVariableDeclaration(
- AstNode* node, const std::string& name, bool is_const,
- const base::Optional<const Type*>& type,
- const base::Optional<VisitResult>& initialization = {});
-
- void GenerateParameter(const std::string& parameter_name);
-
- void GenerateParameterList(const NameVector& list, size_t first = 0);
+ void GenerateAssignToLocation(const LocationReference& reference,
+ const VisitResult& assignment_value);
VisitResult GenerateCall(const std::string& callable_name,
Arguments parameters,
@@ -213,7 +278,7 @@ class ImplementationVisitor : public FileVisitor {
bool GenerateLabeledStatementBlocks(
const std::vector<Statement*>& blocks,
- const std::vector<Label*>& statement_labels, Label* merge_label);
+ const std::vector<Label*>& statement_labels, Block* merge_block);
void GenerateBranch(const VisitResult& condition, Label* true_label,
Label* false_label);
@@ -221,7 +286,7 @@ class ImplementationVisitor : public FileVisitor {
bool GenerateExpressionBranch(Expression* expression,
const std::vector<Label*>& statement_labels,
const std::vector<Statement*>& statement_blocks,
- Label* merge_label);
+ Block* merge_block);
void GenerateMacroFunctionDeclaration(std::ostream& o,
const std::string& macro_prefix,
@@ -242,25 +307,40 @@ class ImplementationVisitor : public FileVisitor {
Visit(callable, MakeSignature(signature), body);
}
- std::string NewTempVariable();
-
- std::string GenerateNewTempVariable(const Type* type);
-
- void GenerateLabelDefinition(Label* label, AstNode* node = nullptr);
+ void CreateBlockForLabel(Label* label, Stack<const Type*> stack);
void GenerateLabelBind(Label* label);
- void GenerateLabelGoto(Label* label);
+ StackRange GenerateLabelGoto(Label* label,
+ base::Optional<StackRange> arguments = {});
std::vector<Label*> LabelsFromIdentifiers(
const std::vector<std::string>& names);
+ StackRange LowerParameter(const Type* type, const std::string& parameter_name,
+ Stack<std::string>* lowered_parameters);
+
+ std::string ExternalLabelParameterName(Label* label, size_t i);
+
std::ostream& source_out() { return module_->source_stream(); }
std::ostream& header_out() { return module_->header_stream(); }
- size_t indent_;
- int32_t next_temp_;
+ CfgAssembler& assembler() { return *assembler_; }
+
+ void SetReturnValue(VisitResult return_value) {
+ DCHECK_IMPLIES(return_value_, *return_value_ == return_value);
+ return_value_ = std::move(return_value);
+ }
+
+ VisitResult GetAndClearReturnValue() {
+ VisitResult return_value = *return_value_;
+ return_value_ = base::nullopt;
+ return return_value;
+ }
+
+ base::Optional<CfgAssembler> assembler_;
+ base::Optional<VisitResult> return_value_;
};
} // namespace torque