// 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_
|