// Copyright 2017 the V8 project authors. All rights reserved. // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. #ifndef V8_TORQUE_IMPLEMENTATION_VISITOR_H_ #define V8_TORQUE_IMPLEMENTATION_VISITOR_H_ #include #include "src/base/macros.h" #include "src/torque/ast.h" #include "src/torque/file-visitor.h" #include "src/torque/global-context.h" #include "src/torque/types.h" #include "src/torque/utils.h" 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; }; class ImplementationVisitor : public FileVisitor { public: explicit ImplementationVisitor(GlobalContext& global_context) : FileVisitor(global_context), indent_(0), next_temp_(0) {} void Visit(Ast* ast) { Visit(ast->default_module()); } VisitResult Visit(Expression* expr); const Type* Visit(Statement* stmt); void Visit(Declaration* decl); VisitResult Visit(StructExpression* decl); LocationReference GetLocationReference(LocationExpression* location); LocationReference GetLocationReference(IdentifierExpression* expr) { return LocationReference(declarations()->LookupValue(expr->name), {}, {}); } LocationReference GetLocationReference(FieldAccessExpression* expr); LocationReference GetLocationReference(ElementAccessExpression* expr) { return LocationReference({}, Visit(expr->array), Visit(expr->index)); } std::string RValueFlattenStructs(VisitResult result); 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 GetBuiltinCode(Builtin* builtin); VisitResult Visit(IdentifierExpression* expr); VisitResult Visit(FieldAccessExpression* expr) { return GenerateFetchFromLocation(expr, GetLocationReference(expr)); } VisitResult Visit(ElementAccessExpression* expr) { return GenerateFetchFromLocation(expr, GetLocationReference(expr)); } void Visit(ModuleDeclaration* decl); void Visit(DefaultModuleDeclaration* decl) { Visit(implicit_cast(decl)); } void Visit(ExplicitModuleDeclaration* decl) { Visit(implicit_cast(decl)); } void Visit(TypeDeclaration* decl) {} void Visit(TypeAliasDeclaration* decl) {} void Visit(ExternConstDeclaration* decl) {} void Visit(StructDeclaration* decl); void Visit(StandardDeclaration* decl); void Visit(GenericDeclaration* decl) {} void Visit(SpecializationDeclaration* decl); void Visit(TorqueMacroDeclaration* decl, const Signature& signature, Statement* body); void Visit(TorqueBuiltinDeclaration* decl, const Signature& signature, Statement* body); void Visit(ExternalMacroDeclaration* decl, const Signature& signature, Statement* body) {} void Visit(ExternalBuiltinDeclaration* decl, const Signature& signature, Statement* body) {} void Visit(ExternalRuntimeDeclaration* decl, const Signature& signature, Statement* body) {} void Visit(CallableNode* decl, const Signature& signature, Statement* body); void Visit(ConstDeclaration* decl); VisitResult Visit(CallExpression* expr, bool is_tail = false); const Type* Visit(TailCallStatement* stmt); VisitResult Visit(ConditionalExpression* expr); VisitResult Visit(LogicalOrExpression* expr); VisitResult Visit(LogicalAndExpression* expr); VisitResult Visit(IncrementDecrementExpression* expr); VisitResult Visit(AssignmentExpression* expr); VisitResult Visit(StringLiteralExpression* expr); VisitResult Visit(NumberLiteralExpression* expr); VisitResult Visit(AssumeTypeImpossibleExpression* expr); const Type* Visit(TryLabelStatement* stmt); const Type* Visit(ReturnStatement* stmt); const Type* Visit(GotoStatement* stmt); const Type* Visit(IfStatement* stmt); const Type* Visit(WhileStatement* stmt); const Type* Visit(BreakStatement* stmt); const Type* Visit(ContinueStatement* stmt); const Type* Visit(ForLoopStatement* stmt); const Type* Visit(VarDeclarationStatement* stmt); const Type* Visit(ForOfLoopStatement* stmt); const Type* Visit(BlockStatement* block); const Type* Visit(ExpressionStatement* stmt); const Type* Visit(DebugStatement* stmt); const Type* Visit(AssertStatement* stmt); void BeginModuleFile(Module* module); void EndModuleFile(Module* module); void GenerateImplementation(const std::string& dir, Module* module); private: std::string GetBaseAssemblerName(Module* module); std::string GetDSLAssemblerName(Module* module); void GenerateIndent(); class ScopedIndent { 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_++; } ~ScopedIndent() { visitor_->indent_--; visitor_->GenerateIndent(); visitor_->source_out() << "}"; if (new_lines_) visitor_->source_out() << "\n"; } private: bool new_lines_; ImplementationVisitor* visitor_; }; 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* 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& initialization); Variable* GenerateVariableDeclaration( AstNode* node, const std::string& name, bool is_const, const base::Optional& type, const base::Optional& initialization = {}); void GenerateParameter(const std::string& parameter_name); void GenerateParameterList(const NameVector& list, size_t first = 0); VisitResult GenerateCall(const std::string& callable_name, Arguments parameters, const TypeVector& specialization_types = {}, bool tail_call = false); VisitResult GeneratePointerCall(Expression* callee, const Arguments& parameters, bool tail_call); bool GenerateLabeledStatementBlocks( const std::vector& blocks, const std::vector& statement_labels, Label* merge_label); void GenerateBranch(const VisitResult& condition, Label* true_label, Label* false_label); bool GenerateExpressionBranch(Expression* expression, const std::vector& statement_labels, const std::vector& statement_blocks, Label* merge_label); void GenerateMacroFunctionDeclaration(std::ostream& o, const std::string& macro_prefix, Macro* macro); void GenerateFunctionDeclaration(std::ostream& o, const std::string& macro_prefix, const std::string& name, const Signature& signature, const NameVector& parameter_names); VisitResult GenerateImplicitConvert(const Type* destination_type, VisitResult source); void Specialize(const SpecializationKey& key, CallableNode* callable, const CallableNodeSignature* signature, Statement* body) override { Declarations::GenericScopeActivator scope(declarations(), key); Visit(callable, MakeSignature(signature), body); } std::string NewTempVariable(); std::string GenerateNewTempVariable(const Type* type); void GenerateLabelDefinition(Label* label, AstNode* node = nullptr); void GenerateLabelBind(Label* label); void GenerateLabelGoto(Label* label); std::vector LabelsFromIdentifiers( const std::vector& names); std::ostream& source_out() { return module_->source_stream(); } std::ostream& header_out() { return module_->header_stream(); } size_t indent_; int32_t next_temp_; }; } // namespace torque } // namespace internal } // namespace v8 #endif // V8_TORQUE_IMPLEMENTATION_VISITOR_H_