| // 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_DECLARABLE_H_ | |
| #define V8_TORQUE_DECLARABLE_H_ | |
| #include <cassert> | |
| #include <string> | |
| #include "src/base/functional.h" | |
| #include "src/base/logging.h" | |
| #include "src/torque/ast.h" | |
| #include "src/torque/types.h" | |
| #include "src/torque/utils.h" | |
| namespace v8 { | |
| namespace internal { | |
| namespace torque { | |
| class Scope; | |
| class ScopeChain; | |
| class Generic; | |
| class Declarable { | |
| public: | |
| virtual ~Declarable() {} | |
| enum Kind { | |
| kVariable, | |
| kParameter, | |
| kMacro, | |
| kMacroList, | |
| kBuiltin, | |
| kRuntimeFunction, | |
| kGeneric, | |
| kGenericList, | |
| kTypeAlias, | |
| kLabel, | |
| kExternConstant, | |
| kModuleConstant | |
| }; | |
| Kind kind() const { return kind_; } | |
| bool IsMacro() const { return kind() == kMacro; } | |
| bool IsBuiltin() const { return kind() == kBuiltin; } | |
| bool IsRuntimeFunction() const { return kind() == kRuntimeFunction; } | |
| bool IsGeneric() const { return kind() == kGeneric; } | |
| bool IsTypeAlias() const { return kind() == kTypeAlias; } | |
| bool IsParameter() const { return kind() == kParameter; } | |
| bool IsLabel() const { return kind() == kLabel; } | |
| bool IsVariable() const { return kind() == kVariable; } | |
| bool IsMacroList() const { return kind() == kMacroList; } | |
| bool IsGenericList() const { return kind() == kGenericList; } | |
| bool IsExternConstant() const { return kind() == kExternConstant; } | |
| bool IsModuleConstant() const { return kind() == kModuleConstant; } | |
| bool IsValue() const { | |
| return IsVariable() || IsExternConstant() || IsParameter() || | |
| IsModuleConstant(); | |
| } | |
| virtual const char* type_name() const { return "<<unknown>>"; } | |
| protected: | |
| explicit Declarable(Kind kind) : kind_(kind) {} | |
| private: | |
| const Kind kind_; | |
| }; | |
| #define DECLARE_DECLARABLE_BOILERPLATE(x, y) \ | |
| static x* cast(Declarable* declarable) { \ | |
| DCHECK(declarable->Is##x()); \ | |
| return static_cast<x*>(declarable); \ | |
| } \ | |
| static const x* cast(const Declarable* declarable) { \ | |
| DCHECK(declarable->Is##x()); \ | |
| return static_cast<const x*>(declarable); \ | |
| } \ | |
| const char* type_name() const override { return #y; } \ | |
| static x* DynamicCast(Declarable* declarable) { \ | |
| if (!declarable) return nullptr; \ | |
| if (!declarable->Is##x()) return nullptr; \ | |
| return static_cast<x*>(declarable); \ | |
| } \ | |
| static const x* DynamicCast(const Declarable* declarable) { \ | |
| if (!declarable) return nullptr; \ | |
| if (!declarable->Is##x()) return nullptr; \ | |
| return static_cast<const x*>(declarable); \ | |
| } | |
| class Value : public Declarable { | |
| public: | |
| const std::string& name() const { return name_; } | |
| virtual bool IsConst() const { return true; } | |
| virtual std::string value() const = 0; | |
| virtual std::string RValue() const { return value(); } | |
| DECLARE_DECLARABLE_BOILERPLATE(Value, value); | |
| const Type* type() const { return type_; } | |
| protected: | |
| Value(Kind kind, const Type* type, const std::string& name) | |
| : Declarable(kind), type_(type), name_(name) {} | |
| private: | |
| const Type* type_; | |
| std::string name_; | |
| }; | |
| class Parameter : public Value { | |
| public: | |
| DECLARE_DECLARABLE_BOILERPLATE(Parameter, parameter); | |
| std::string value() const override { return var_name_; } | |
| private: | |
| friend class Declarations; | |
| Parameter(const std::string& name, const Type* type, | |
| const std::string& var_name) | |
| : Value(Declarable::kParameter, type, name), var_name_(var_name) {} | |
| std::string var_name_; | |
| }; | |
| class ModuleConstant : public Value { | |
| public: | |
| DECLARE_DECLARABLE_BOILERPLATE(ModuleConstant, constant); | |
| std::string value() const override { UNREACHABLE(); } | |
| std::string RValue() const override { return name() + "()"; } | |
| private: | |
| friend class Declarations; | |
| explicit ModuleConstant(const std::string& name, const Type* type) | |
| : Value(Declarable::kModuleConstant, type, name) {} | |
| }; | |
| class Variable : public Value { | |
| public: | |
| DECLARE_DECLARABLE_BOILERPLATE(Variable, variable); | |
| bool IsConst() const override { return const_; } | |
| std::string value() const override { return value_; } | |
| std::string RValue() const override; | |
| void Define() { | |
| if (defined_ && IsConst()) { | |
| ReportError("Cannot re-define a const-bound variable."); | |
| } | |
| defined_ = true; | |
| } | |
| bool IsDefined() const { return defined_; } | |
| private: | |
| friend class Declarations; | |
| Variable(const std::string& name, const std::string& value, const Type* type, | |
| bool is_const) | |
| : Value(Declarable::kVariable, type, name), | |
| value_(value), | |
| defined_(false), | |
| const_(is_const) { | |
| DCHECK_IMPLIES(type->IsConstexpr(), IsConst()); | |
| } | |
| std::string value_; | |
| bool defined_; | |
| bool const_; | |
| }; | |
| class Label : public Declarable { | |
| public: | |
| void AddVariable(Variable* var) { parameters_.push_back(var); } | |
| std::string name() const { return name_; } | |
| std::string generated() const { return generated_; } | |
| Variable* GetParameter(size_t i) const { return parameters_[i]; } | |
| size_t GetParameterCount() const { return parameters_.size(); } | |
| const std::vector<Variable*>& GetParameters() const { return parameters_; } | |
| DECLARE_DECLARABLE_BOILERPLATE(Label, label); | |
| void MarkUsed() { used_ = true; } | |
| bool IsUsed() const { return used_; } | |
| private: | |
| friend class Declarations; | |
| explicit Label(const std::string& name) | |
| : Declarable(Declarable::kLabel), | |
| name_(name), | |
| generated_("label_" + name + "_" + std::to_string(next_id_++)), | |
| used_(false) {} | |
| std::string name_; | |
| std::string generated_; | |
| std::vector<Variable*> parameters_; | |
| static size_t next_id_; | |
| bool used_; | |
| }; | |
| class ExternConstant : public Value { | |
| public: | |
| DECLARE_DECLARABLE_BOILERPLATE(ExternConstant, constant); | |
| std::string value() const override { return value_; } | |
| private: | |
| friend class Declarations; | |
| explicit ExternConstant(const std::string& name, const Type* type, | |
| const std::string& value) | |
| : Value(Declarable::kExternConstant, type, name), value_(value) {} | |
| std::string value_; | |
| }; | |
| class Callable : public Declarable { | |
| public: | |
| static Callable* cast(Declarable* declarable) { | |
| assert(declarable->IsMacro() || declarable->IsBuiltin() || | |
| declarable->IsRuntimeFunction()); | |
| return static_cast<Callable*>(declarable); | |
| } | |
| static const Callable* cast(const Declarable* declarable) { | |
| assert(declarable->IsMacro() || declarable->IsBuiltin() || | |
| declarable->IsRuntimeFunction()); | |
| return static_cast<const Callable*>(declarable); | |
| } | |
| const std::string& name() const { return name_; } | |
| const Signature& signature() const { return signature_; } | |
| const NameVector& parameter_names() const { | |
| return signature_.parameter_names; | |
| } | |
| bool HasReturnValue() const { | |
| return !signature_.return_type->IsVoidOrNever(); | |
| } | |
| void IncrementReturns() { ++returns_; } | |
| bool HasReturns() const { return returns_; } | |
| base::Optional<Generic*> generic() const { return generic_; } | |
| protected: | |
| Callable(Declarable::Kind kind, const std::string& name, | |
| const Signature& signature, base::Optional<Generic*> generic) | |
| : Declarable(kind), | |
| name_(name), | |
| signature_(signature), | |
| returns_(0), | |
| generic_(generic) {} | |
| private: | |
| std::string name_; | |
| Signature signature_; | |
| size_t returns_; | |
| base::Optional<Generic*> generic_; | |
| }; | |
| class Macro : public Callable { | |
| public: | |
| DECLARE_DECLARABLE_BOILERPLATE(Macro, macro); | |
| private: | |
| friend class Declarations; | |
| Macro(const std::string& name, const Signature& signature, | |
| base::Optional<Generic*> generic) | |
| : Callable(Declarable::kMacro, name, signature, generic) { | |
| if (signature.parameter_types.var_args) { | |
| ReportError("Varargs are not supported for macros."); | |
| } | |
| } | |
| }; | |
| class MacroList : public Declarable { | |
| public: | |
| DECLARE_DECLARABLE_BOILERPLATE(MacroList, macro_list); | |
| const std::vector<Macro*>& list() { return list_; } | |
| Macro* AddMacro(Macro* macro) { | |
| list_.emplace_back(macro); | |
| return macro; | |
| } | |
| private: | |
| friend class Declarations; | |
| MacroList() : Declarable(Declarable::kMacroList) {} | |
| std::vector<Macro*> list_; | |
| }; | |
| class Builtin : public Callable { | |
| public: | |
| enum Kind { kStub, kFixedArgsJavaScript, kVarArgsJavaScript }; | |
| DECLARE_DECLARABLE_BOILERPLATE(Builtin, builtin); | |
| Kind kind() const { return kind_; } | |
| bool IsStub() const { return kind_ == kStub; } | |
| bool IsVarArgsJavaScript() const { return kind_ == kVarArgsJavaScript; } | |
| bool IsFixedArgsJavaScript() const { return kind_ == kFixedArgsJavaScript; } | |
| bool IsExternal() const { return external_; } | |
| private: | |
| friend class Declarations; | |
| Builtin(const std::string& name, Builtin::Kind kind, bool external, | |
| const Signature& signature, base::Optional<Generic*> generic) | |
| : Callable(Declarable::kBuiltin, name, signature, generic), | |
| kind_(kind), | |
| external_(external) {} | |
| Kind kind_; | |
| bool external_; | |
| }; | |
| class RuntimeFunction : public Callable { | |
| public: | |
| DECLARE_DECLARABLE_BOILERPLATE(RuntimeFunction, runtime); | |
| private: | |
| friend class Declarations; | |
| RuntimeFunction(const std::string& name, const Signature& signature, | |
| base::Optional<Generic*> generic) | |
| : Callable(Declarable::kRuntimeFunction, name, signature, generic) {} | |
| }; | |
| class Generic : public Declarable { | |
| public: | |
| DECLARE_DECLARABLE_BOILERPLATE(Generic, generic); | |
| GenericDeclaration* declaration() const { return declaration_; } | |
| const std::string& name() const { return name_; } | |
| Module* module() const { return module_; } | |
| private: | |
| friend class Declarations; | |
| Generic(const std::string& name, Module* module, | |
| GenericDeclaration* declaration) | |
| : Declarable(Declarable::kGeneric), | |
| name_(name), | |
| module_(module), | |
| declaration_(declaration) {} | |
| std::string name_; | |
| Module* module_; | |
| GenericDeclaration* declaration_; | |
| }; | |
| class GenericList : public Declarable { | |
| public: | |
| DECLARE_DECLARABLE_BOILERPLATE(GenericList, generic_list); | |
| const std::vector<Generic*>& list() { return list_; } | |
| Generic* AddGeneric(Generic* generic) { | |
| list_.push_back(generic); | |
| return generic; | |
| } | |
| private: | |
| friend class Declarations; | |
| GenericList() : Declarable(Declarable::kGenericList) {} | |
| std::vector<Generic*> list_; | |
| }; | |
| typedef std::pair<Generic*, TypeVector> SpecializationKey; | |
| class TypeAlias : public Declarable { | |
| public: | |
| DECLARE_DECLARABLE_BOILERPLATE(TypeAlias, type_alias); | |
| const Type* type() const { return type_; } | |
| private: | |
| friend class Declarations; | |
| explicit TypeAlias(const Type* type) | |
| : Declarable(Declarable::kTypeAlias), type_(type) {} | |
| const Type* type_; | |
| }; | |
| void PrintLabel(std::ostream& os, const Label& l, bool with_names); | |
| std::ostream& operator<<(std::ostream& os, const Callable& m); | |
| std::ostream& operator<<(std::ostream& os, const Variable& v); | |
| std::ostream& operator<<(std::ostream& os, const Builtin& b); | |
| std::ostream& operator<<(std::ostream& os, const Label& l); | |
| std::ostream& operator<<(std::ostream& os, const RuntimeFunction& b); | |
| std::ostream& operator<<(std::ostream& os, const Generic& g); | |
| #undef DECLARE_DECLARABLE_BOILERPLATE | |
| } // namespace torque | |
| } // namespace internal | |
| } // namespace v8 | |
| #endif // V8_TORQUE_DECLARABLE_H_ |