// 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.
|
|
#include "src/torque/declarations.h"
|
#include "src/torque/declarable.h"
|
#include "src/torque/type-oracle.h"
|
|
namespace v8 {
|
namespace internal {
|
namespace torque {
|
|
Scope* Declarations::GetModuleScope(const Module* module) {
|
auto i = module_scopes_.find(module);
|
if (i != module_scopes_.end()) return i->second;
|
Scope* result = chain_.NewScope();
|
module_scopes_[module] = result;
|
return result;
|
}
|
|
Scope* Declarations::GetNodeScope(const AstNode* node, bool reset_scope) {
|
std::pair<const AstNode*, TypeVector> key(
|
node, current_generic_specialization_ == nullptr
|
? TypeVector()
|
: current_generic_specialization_->second);
|
if (!reset_scope) {
|
auto i = scopes_.find(key);
|
if (i != scopes_.end()) return i->second;
|
}
|
Scope* result = chain_.NewScope();
|
scopes_[key] = result;
|
return result;
|
}
|
|
Scope* Declarations::GetGenericScope(Generic* generic,
|
const TypeVector& types) {
|
std::pair<const AstNode*, TypeVector> key(generic->declaration()->callable,
|
types);
|
auto i = scopes_.find(key);
|
if (i != scopes_.end()) return i->second;
|
Scope* result = chain_.NewScope();
|
scopes_[key] = result;
|
return result;
|
}
|
|
bool Declarations::IsDeclaredInCurrentScope(const std::string& name) {
|
return chain_.ShallowLookup(name) != nullptr;
|
}
|
|
void Declarations::CheckAlreadyDeclared(const std::string& name,
|
const char* new_type) {
|
if (IsDeclaredInCurrentScope(name)) {
|
std::stringstream s;
|
s << "cannot redeclare " << name << " (type " << new_type << ")";
|
ReportError(s.str());
|
}
|
}
|
|
const Type* Declarations::LookupType(const std::string& name) {
|
Declarable* raw = Lookup(name);
|
if (raw->IsTypeAlias()) {
|
return TypeAlias::cast(raw)->type();
|
}
|
std::stringstream s;
|
s << "declaration \"" << name << "\" is not a Type";
|
ReportError(s.str());
|
return nullptr;
|
}
|
|
const Type* Declarations::LookupGlobalType(const std::string& name) {
|
Declarable* raw = LookupGlobalScope(name);
|
if (!raw->IsTypeAlias()) {
|
std::stringstream s;
|
s << "declaration \"" << name << "\" is not a Type";
|
ReportError(s.str());
|
}
|
return TypeAlias::cast(raw)->type();
|
}
|
|
const Type* Declarations::GetType(TypeExpression* type_expression) {
|
if (auto* basic = BasicTypeExpression::DynamicCast(type_expression)) {
|
std::string name =
|
(basic->is_constexpr ? CONSTEXPR_TYPE_PREFIX : "") + basic->name;
|
return LookupType(name);
|
} else if (auto* union_type = UnionTypeExpression::cast(type_expression)) {
|
return TypeOracle::GetUnionType(GetType(union_type->a),
|
GetType(union_type->b));
|
} else {
|
auto* function_type_exp = FunctionTypeExpression::cast(type_expression);
|
TypeVector argument_types;
|
for (TypeExpression* type_exp : function_type_exp->parameters) {
|
argument_types.push_back(GetType(type_exp));
|
}
|
return TypeOracle::GetFunctionPointerType(
|
argument_types, GetType(function_type_exp->return_type));
|
}
|
}
|
|
Builtin* Declarations::FindSomeInternalBuiltinWithType(
|
const FunctionPointerType* type) {
|
for (auto& declarable : declarables_) {
|
if (Builtin* builtin = Builtin::DynamicCast(declarable.get())) {
|
if (!builtin->IsExternal() && builtin->kind() == Builtin::kStub &&
|
builtin->signature().return_type == type->return_type() &&
|
builtin->signature().parameter_types.types ==
|
type->parameter_types()) {
|
return builtin;
|
}
|
}
|
}
|
return nullptr;
|
}
|
|
Value* Declarations::LookupValue(const std::string& name) {
|
Declarable* d = Lookup(name);
|
if (!d->IsValue()) {
|
std::stringstream s;
|
s << "declaration \"" << name << "\" is not a Value";
|
ReportError(s.str());
|
}
|
return Value::cast(d);
|
}
|
|
Label* Declarations::LookupLabel(const std::string& name) {
|
Declarable* d = Lookup(name);
|
if (!d->IsLabel()) {
|
std::stringstream s;
|
s << "declaration \"" << name << "\" is not a Label";
|
ReportError(s.str());
|
}
|
return Label::cast(d);
|
}
|
|
Macro* Declarations::TryLookupMacro(const std::string& name,
|
const TypeVector& types) {
|
Declarable* declarable = TryLookup(name);
|
if (declarable != nullptr) {
|
if (declarable->IsMacroList()) {
|
for (auto& m : MacroList::cast(declarable)->list()) {
|
if (m->signature().parameter_types.types == types &&
|
!m->signature().parameter_types.var_args) {
|
return m;
|
}
|
}
|
}
|
}
|
return nullptr;
|
}
|
|
Macro* Declarations::LookupMacro(const std::string& name,
|
const TypeVector& types) {
|
Macro* result = TryLookupMacro(name, types);
|
if (result != nullptr) return result;
|
std::stringstream stream;
|
stream << "macro " << name << " with parameter types " << types
|
<< " is not defined";
|
ReportError(stream.str());
|
return nullptr;
|
}
|
|
Builtin* Declarations::LookupBuiltin(const std::string& name) {
|
Declarable* declarable = Lookup(name);
|
if (declarable != nullptr) {
|
if (declarable->IsBuiltin()) {
|
return Builtin::cast(declarable);
|
}
|
ReportError(name + " is not a builtin");
|
}
|
ReportError(std::string("builtin ") + name + " is not defined");
|
return nullptr;
|
}
|
|
GenericList* Declarations::LookupGeneric(const std::string& name) {
|
Declarable* declarable_list = Lookup(name);
|
if (declarable_list != nullptr) {
|
if (declarable_list->IsGenericList()) {
|
return GenericList::cast(declarable_list);
|
}
|
ReportError(name + " is not a generic");
|
}
|
ReportError(std::string("generic ") + name + " is not defined");
|
return nullptr;
|
}
|
|
ModuleConstant* Declarations::LookupModuleConstant(const std::string& name) {
|
Declarable* declarable = Lookup(name);
|
if (declarable != nullptr) {
|
if (declarable->IsModuleConstant()) {
|
return ModuleConstant::cast(declarable);
|
}
|
ReportError(name + " is not a constant");
|
}
|
ReportError(std::string("constant \"") + name + "\" is not defined");
|
return nullptr;
|
}
|
|
const AbstractType* Declarations::DeclareAbstractType(
|
const std::string& name, const std::string& generated,
|
base::Optional<const AbstractType*> non_constexpr_version,
|
const base::Optional<std::string>& parent) {
|
CheckAlreadyDeclared(name, "type");
|
const Type* parent_type = nullptr;
|
if (parent) {
|
Declarable* maybe_parent_type = Lookup(*parent);
|
if (maybe_parent_type == nullptr) {
|
std::stringstream s;
|
s << "cannot find parent type \"" << *parent << "\"";
|
ReportError(s.str());
|
}
|
if (!maybe_parent_type->IsTypeAlias()) {
|
std::stringstream s;
|
s << "parent \"" << *parent << "\" of type \"" << name << "\""
|
<< " is not a type";
|
ReportError(s.str());
|
}
|
parent_type = TypeAlias::cast(maybe_parent_type)->type();
|
}
|
const AbstractType* type = TypeOracle::GetAbstractType(
|
parent_type, name, generated, non_constexpr_version);
|
DeclareType(name, type);
|
return type;
|
}
|
|
void Declarations::DeclareType(const std::string& name, const Type* type) {
|
CheckAlreadyDeclared(name, "type");
|
TypeAlias* result = new TypeAlias(type);
|
Declare(name, std::unique_ptr<TypeAlias>(result));
|
}
|
|
void Declarations::DeclareStruct(Module* module, const std::string& name,
|
const std::vector<NameAndType>& fields) {
|
const StructType* new_type = TypeOracle::GetStructType(module, name, fields);
|
DeclareType(name, new_type);
|
}
|
|
Label* Declarations::DeclareLabel(const std::string& name) {
|
CheckAlreadyDeclared(name, "label");
|
Label* result = new Label(name);
|
Declare(name, std::unique_ptr<Declarable>(result));
|
return result;
|
}
|
|
MacroList* Declarations::GetMacroListForName(const std::string& name,
|
const Signature& signature) {
|
auto previous = chain_.Lookup(name);
|
MacroList* macro_list = nullptr;
|
if (previous == nullptr) {
|
macro_list = new MacroList();
|
Declare(name, std::unique_ptr<Declarable>(macro_list));
|
} else if (!previous->IsMacroList()) {
|
std::stringstream s;
|
s << "cannot redeclare non-macro " << name << " as a macro";
|
ReportError(s.str());
|
} else {
|
macro_list = MacroList::cast(previous);
|
}
|
for (auto& macro : macro_list->list()) {
|
if (signature.parameter_types.types ==
|
macro->signature().parameter_types.types &&
|
signature.parameter_types.var_args ==
|
macro->signature().parameter_types.var_args) {
|
std::stringstream s;
|
s << "cannot redeclare " << name
|
<< " as a macro with identical parameter list "
|
<< signature.parameter_types;
|
ReportError(s.str());
|
}
|
}
|
return macro_list;
|
}
|
|
Macro* Declarations::DeclareMacro(const std::string& name,
|
const Signature& signature,
|
base::Optional<std::string> op) {
|
Macro* macro = RegisterDeclarable(
|
std::unique_ptr<Macro>(new Macro(name, signature, GetCurrentGeneric())));
|
GetMacroListForName(name, signature)->AddMacro(macro);
|
if (op) GetMacroListForName(*op, signature)->AddMacro(macro);
|
return macro;
|
}
|
|
Builtin* Declarations::DeclareBuiltin(const std::string& name,
|
Builtin::Kind kind, bool external,
|
const Signature& signature) {
|
CheckAlreadyDeclared(name, "builtin");
|
Builtin* result =
|
new Builtin(name, kind, external, signature, GetCurrentGeneric());
|
Declare(name, std::unique_ptr<Declarable>(result));
|
return result;
|
}
|
|
RuntimeFunction* Declarations::DeclareRuntimeFunction(
|
const std::string& name, const Signature& signature) {
|
CheckAlreadyDeclared(name, "runtime function");
|
RuntimeFunction* result =
|
new RuntimeFunction(name, signature, GetCurrentGeneric());
|
Declare(name, std::unique_ptr<Declarable>(result));
|
return result;
|
}
|
|
Variable* Declarations::DeclareVariable(const std::string& var,
|
const Type* type, bool is_const) {
|
std::string name(var + "_" +
|
std::to_string(GetNextUniqueDeclarationNumber()));
|
std::replace(name.begin(), name.end(), '.', '_');
|
CheckAlreadyDeclared(var, "variable");
|
Variable* result = new Variable(var, name, type, is_const);
|
Declare(var, std::unique_ptr<Declarable>(result));
|
return result;
|
}
|
|
Parameter* Declarations::DeclareParameter(const std::string& name,
|
const std::string& var_name,
|
const Type* type) {
|
CheckAlreadyDeclared(name, "parameter");
|
Parameter* result = new Parameter(name, type, var_name);
|
Declare(name, std::unique_ptr<Declarable>(result));
|
return result;
|
}
|
|
Label* Declarations::DeclarePrivateLabel(const std::string& raw_name) {
|
std::string name =
|
raw_name + "_" + std::to_string(GetNextUniqueDeclarationNumber());
|
CheckAlreadyDeclared(name, "label");
|
Label* result = new Label(name);
|
Declare(name, std::unique_ptr<Declarable>(result));
|
return result;
|
}
|
|
void Declarations::DeclareExternConstant(const std::string& name,
|
const Type* type,
|
const std::string& value) {
|
CheckAlreadyDeclared(name, "constant, parameter or arguments");
|
ExternConstant* result = new ExternConstant(name, type, value);
|
Declare(name, std::unique_ptr<Declarable>(result));
|
}
|
|
ModuleConstant* Declarations::DeclareModuleConstant(const std::string& name,
|
const Type* type) {
|
CheckAlreadyDeclared(name, "module constant");
|
ModuleConstant* result = new ModuleConstant(name, type);
|
Declare(name, std::unique_ptr<Declarable>(result));
|
return result;
|
}
|
|
Generic* Declarations::DeclareGeneric(const std::string& name, Module* module,
|
GenericDeclaration* generic) {
|
auto previous = chain_.Lookup(name);
|
GenericList* generic_list = nullptr;
|
if (previous == nullptr) {
|
generic_list = new GenericList();
|
Declare(name, std::unique_ptr<Declarable>(generic_list));
|
} else if (!previous->IsGenericList()) {
|
std::stringstream s;
|
s << "cannot redeclare non-generic " << name << " as a generic";
|
ReportError(s.str());
|
} else {
|
generic_list = GenericList::cast(previous);
|
}
|
Generic* result = RegisterDeclarable(
|
std::unique_ptr<Generic>(new Generic(name, module, generic)));
|
generic_list->AddGeneric(result);
|
generic_declaration_scopes_[result] = GetScopeChainSnapshot();
|
return result;
|
}
|
|
TypeVector Declarations::GetCurrentSpecializationTypeNamesVector() {
|
TypeVector result;
|
if (current_generic_specialization_ != nullptr) {
|
result = current_generic_specialization_->second;
|
}
|
return result;
|
}
|
|
base::Optional<Generic*> Declarations::GetCurrentGeneric() {
|
if (current_generic_specialization_ != nullptr) {
|
return current_generic_specialization_->first;
|
}
|
return base::nullopt;
|
}
|
|
std::string GetGeneratedCallableName(const std::string& name,
|
const TypeVector& specialized_types) {
|
std::string result = name;
|
for (auto type : specialized_types) {
|
std::string type_string = type->MangledName();
|
result += std::to_string(type_string.size()) + type_string;
|
}
|
return result;
|
}
|
|
} // namespace torque
|
} // namespace internal
|
} // namespace v8
|