Refactor/cleanup various Torque classes, inclduing making Type a Declarable

This is a preparatory step for implementing generics. Along the way, clean up
and encapsulate a bunch of code, including:

* Fully encapsulate Scope by adding the new class ScopeChain that provide an
  abstraction for creating and activating scopes.
* Untangle Modules and Scopes.
* Unify scope activation so that it is always associated with an AST node
  and triggered by a RAII helper class.
* Unify (somewhat) how builtins and macros are created, fixing a few
  inconsistencies with when and how parameters and their types are declared.
* Create a new Declarations class that brokers between the visitor classes and
  the ScopeChain. This moves handling of declaration-related errors out of the
  visitors but also makes it possible to do so without polluting Scope and
  ScopeChain with details about resolving SourcePositions in error cases.

Change-Id: I180017d4cf39ccf5ef1d20b84f53284c252f8d87
Reviewed-on: https://chromium-review.googlesource.com/1038504
Commit-Queue: Daniel Clifford <danno@chromium.org>
Reviewed-by: Tobias Tebbi <tebbi@chromium.org>
Cr-Commit-Position: refs/heads/master@{#52947}
This commit is contained in:
Daniel Clifford 2018-05-03 13:10:26 +02:00 committed by Commit Bot
parent c32f661486
commit 90415437fb
23 changed files with 848 additions and 643 deletions

View File

@ -3036,6 +3036,8 @@ if (current_toolchain == v8_snapshot_toolchain) {
"src/torque/declarable.h",
"src/torque/declaration-visitor.cc",
"src/torque/declaration-visitor.h",
"src/torque/declarations.cc",
"src/torque/declarations.h",
"src/torque/file-visitor.cc",
"src/torque/file-visitor.h",
"src/torque/global-context.h",

View File

@ -134,8 +134,8 @@ extern operator '>' macro Int32GreaterThan(int32, int32): bit;
extern operator '<=' macro Int32LessThanOrEqual(int32, int32): bit;
extern operator '>=' macro Int32GreaterThanOrEqual(int32, int32): bit;
extern operator '==' macro WordEqual(Smi, Smi): bit;
extern operator '!=' macro WordNotEqual(Smi, Smi): bit;
extern operator '==' macro SmiEqual(Smi, Smi): bit;
extern operator '!=' macro SmiNotEqual(Smi, Smi): bit;
extern operator '<' macro SmiLessThan(Smi, Smi): bit;
extern operator '<=' macro SmiLessThanOrEqual(Smi, Smi): bit;
extern operator '>' macro SmiGreaterThan(Smi, Smi): bit;
@ -189,7 +189,7 @@ extern operator '.length' macro LoadStringLengthAsWord(String): intptr;
extern operator '.length' macro GetArgumentsLength(Arguments): intptr;
extern operator '[]' macro GetArgumentValue(Arguments, intptr): Object;
extern operator '[]' macro GetArgumentValue(Arguments, Smi): Object;
extern operator '[]' macro GetArgumentValueSmiIndex(Arguments, Smi): Object;
extern operator 'is<Smi>' macro TaggedIsSmi(Object): bit;
extern operator 'isnt<Smi>' macro TaggedIsNotSmi(Object): bit;
@ -209,12 +209,9 @@ extern operator 'cast<>' macro ConvertFixedArrayBaseToFixedDoubleArray(
extern implicit operator
'convert<>' macro AllocateHeapNumberWithValue(const_float64): Number;
extern implicit operator 'convert<>' macro IntPtrConstant(const_int31): intptr;
extern implicit operator 'convert<>' macro IntPtrConstant(const_int32): intptr;
extern implicit operator 'convert<>' macro Int32Constant(const_int31): int32;
extern implicit operator 'convert<>' macro Int32Constant(const_int32): int32;
extern implicit operator 'convert<>' macro SmiConstant(const_int31): Smi;
extern implicit operator 'convert<>' macro NumberConstant(const_int31): Number;
extern implicit operator 'convert<>' macro NumberConstant(const_int32): Number;
extern operator 'convert<>' macro ChangeInt32ToTagged(int32): Number;
extern operator 'convert<>' macro TruncateWordToWord32(intptr): int32;

View File

@ -11579,8 +11579,8 @@ TNode<Object> CodeStubAssembler::GetArgumentValue(CodeStubArguments* args,
return args->GetOptionalArgumentValue(index);
}
TNode<Object> CodeStubAssembler::GetArgumentValue(CodeStubArguments* args,
TNode<Smi> index) {
TNode<Object> CodeStubAssembler::GetArgumentValueSmiIndex(
CodeStubArguments* args, TNode<Smi> index) {
return args->GetOptionalArgumentValue(SmiUntag(index));
}

View File

@ -2239,7 +2239,8 @@ class V8_EXPORT_PRIVATE CodeStubAssembler : public compiler::CodeAssembler {
TNode<IntPtrT> GetArgumentsLength(CodeStubArguments* args);
TNode<Object> GetArgumentValue(CodeStubArguments* args, TNode<IntPtrT> index);
TNode<Object> GetArgumentValue(CodeStubArguments* args, TNode<Smi> index);
TNode<Object> GetArgumentValueSmiIndex(CodeStubArguments* args,
TNode<Smi> index);
// Support for printf-style debugging
void Print(const char* s);

View File

@ -14,6 +14,7 @@ namespace torque {
namespace {
std::string GetOptionalType(TorqueParser::OptionalTypeContext* context) {
if (!context) return "";
if (!context->type()) return "void";
return context->type()->IDENTIFIER()->getSymbol()->getText();
}
@ -21,15 +22,18 @@ std::string GetOptionalType(TorqueParser::OptionalTypeContext* context) {
LabelAndTypesVector GetOptionalLabelAndTypeList(
TorqueParser::OptionalLabelListContext* context) {
LabelAndTypesVector labels;
for (auto label : context->labelParameter()) {
LabelAndTypes new_label;
new_label.name = label->IDENTIFIER()->getSymbol()->getText();
if (label->typeList() != nullptr) {
for (auto& type : label->typeList()->type()) {
new_label.types.push_back(type->IDENTIFIER()->getSymbol()->getText());
if (context) {
for (auto label : context->labelParameter()) {
LabelAndTypes new_label;
new_label.name = label->IDENTIFIER()->getSymbol()->getText();
if (label->typeList() != nullptr) {
for (auto& type : label->typeList()->type()) {
new_label.types.emplace_back(
type->IDENTIFIER()->getSymbol()->getText());
}
}
labels.emplace_back(new_label);
}
labels.push_back(new_label);
}
return labels;
}
@ -67,6 +71,21 @@ std::string StringLiteralUnquote(const std::string& s) {
} // namespace
ParameterList AstGenerator::GetOptionalParameterList(
TorqueParser::ParameterListContext* context) {
if (context != nullptr) {
return context->accept(this).as<ParameterList>();
} else {
return ParameterList();
}
}
Statement* AstGenerator::GetOptionalHelperBody(
TorqueParser::HelperBodyContext* context) {
if (context) return context->accept(this).as<Statement*>();
return nullptr;
}
antlrcpp::Any AstGenerator::visitParameterList(
TorqueParser::ParameterListContext* context) {
ParameterList result{{}, {}, context->VARARGS(), {}};
@ -117,7 +136,7 @@ antlrcpp::Any AstGenerator::visitMacroDeclaration(
TorqueParser::MacroDeclarationContext* context) {
return base::implicit_cast<Declaration*>(RegisterNode(new MacroDeclaration{
Pos(context), context->IDENTIFIER()->getSymbol()->getText(),
std::move(context->parameterList()->accept(this).as<ParameterList>()),
GetOptionalParameterList(context->parameterList()),
GetOptionalType(context->optionalType()),
GetOptionalLabelAndTypeList(context->optionalLabelList()),
context->helperBody()->accept(this).as<Statement*>()}));
@ -588,9 +607,7 @@ antlrcpp::Any AstGenerator::visitConditionalExpression(
return base::implicit_cast<Expression*>(
RegisterNode(new ConditionalExpression{
Pos(context), condition->accept(this).as<Expression*>(),
context->logicalORExpression(0)->accept(this).as<Expression*>(),
context->logicalORExpression(1)->accept(this).as<Expression*>()}));
}
return context->logicalORExpression(0)->accept(this);

View File

@ -148,6 +148,11 @@ class AstGenerator : public TorqueBaseVisitor {
return node;
}
ParameterList GetOptionalParameterList(
TorqueParser::ParameterListContext* context);
Statement* GetOptionalHelperBody(TorqueParser::HelperBodyContext* context);
void visitSourceFile(SourceFileContext* context);
SourcePosition Pos(antlr4::ParserRuleContext* context);

View File

@ -158,9 +158,32 @@ struct ExplicitModuleDeclaration : ModuleDeclaration {
std::string name;
};
class SourceFileMap {
public:
SourceFileMap() {}
const std::string& GetSource(SourceId id) const {
return sources_[static_cast<int>(id)];
}
std::string PositionAsString(SourcePosition pos) {
return GetSource(pos.source) + ":" + std::to_string(pos.line) + ":" +
std::to_string(pos.column);
}
private:
friend class Ast;
SourceId AddSource(std::string path) {
sources_.push_back(std::move(path));
return static_cast<SourceId>(sources_.size() - 1);
}
std::vector<std::string> sources_;
};
class Ast {
public:
Ast() : default_module_{SourcePosition(), {}} {}
Ast()
: default_module_{SourcePosition(), {}},
source_file_map_(new SourceFileMap()) {}
std::vector<Declaration*>& declarations() {
return default_module_.declarations;
@ -172,21 +195,14 @@ class Ast {
nodes_.emplace_back(std::move(node));
}
SourceId AddSource(std::string path) {
sources_.push_back(std::move(path));
return static_cast<SourceId>(sources_.size() - 1);
return source_file_map_->AddSource(path);
}
const std::string& GetSource(SourceId id) const {
return sources_[static_cast<int>(id)];
}
std::string PositionAsString(SourcePosition pos) {
return GetSource(pos.source) + ":" + std::to_string(pos.line) + ":" +
std::to_string(pos.column);
}
DefaultModuleDeclaration* GetDefaultModule() { return &default_module_; }
DefaultModuleDeclaration* default_module() { return &default_module_; }
SourceFileMap* source_file_map() { return &*source_file_map_; }
private:
DefaultModuleDeclaration default_module_;
std::vector<std::string> sources_;
std::unique_ptr<SourceFileMap> source_file_map_;
std::vector<std::unique_ptr<AstNode>> nodes_;
};

View File

@ -5,6 +5,7 @@
#ifndef V8_TORQUE_DECLARABLE_H_
#define V8_TORQUE_DECLARABLE_H_
#include <cassert>
#include <string>
#include "src/base/logging.h"
@ -16,25 +17,28 @@ namespace internal {
namespace torque {
class Scope;
class ScopeChain;
class Declarable {
public:
virtual ~Declarable() {}
enum Kind {
kVariable = 0,
kTypeImpl,
kVariable,
kParameter,
kMacro,
kMacroList,
kBuiltin,
kRuntime,
kRuntimeFunction,
kLabel,
kConstant
};
explicit Declarable(Kind kind) : kind_(kind) {}
Kind kind() const { return kind_; }
bool IsTypeImpl() const { return kind() == kTypeImpl; }
bool IsMacro() const { return kind() == kMacro; }
bool IsBuiltin() const { return kind() == kBuiltin; }
bool IsRuntime() const { return kind() == kRuntime; }
bool IsRuntimeFunction() const { return kind() == kRuntimeFunction; }
bool IsParameter() const { return kind() == kParameter; }
bool IsLabel() const { return kind() == kLabel; }
bool IsVariable() const { return kind() == kVariable; }
@ -60,6 +64,25 @@ class Declarable {
} \
const char* type_name() const override { return #y; }
class TypeImpl : public Declarable {
public:
DECLARE_DECLARABLE_BOILERPLATE(TypeImpl, type_impl);
TypeImpl(TypeImpl* parent, const std::string& name,
const std::string& generated_type)
: Declarable(Declarable::kTypeImpl),
parent_(parent),
name_(name),
generated_type_(generated_type) {}
TypeImpl* parent() const { return parent_; }
const std::string& name() const { return name_; }
const std::string& generated_type() const { return generated_type_; }
private:
TypeImpl* parent_;
std::string name_;
std::string generated_type_;
};
class Value : public Declarable {
public:
const std::string& name() const { return name_; }
@ -87,7 +110,7 @@ class Parameter : public Value {
std::string GetValueForDeclaration() const override { return var_name_; }
private:
friend class Scope;
friend class Declarations;
Parameter(const std::string& name, Type type, const std::string& var_name)
: Value(Declarable::kParameter, type, name), var_name_(var_name) {}
@ -107,7 +130,7 @@ class Variable : public Value {
bool IsDefined() const { return defined_; }
private:
friend class Scope;
friend class Declarations;
Variable(const std::string& name, const std::string& value, Type type)
: Value(Declarable::kVariable, type, name),
value_(value),
@ -131,7 +154,7 @@ class Label : public Value {
bool IsUsed() const { return used_; }
private:
friend class Scope;
friend class Declarations;
explicit Label(const std::string& name)
: Value(Declarable::kLabel, Type(),
"label_" + name + "_" + std::to_string(next_id_++)),
@ -150,7 +173,7 @@ class Constant : public Value {
std::string GetValueForDeclaration() const override { return value_; }
private:
friend class Scope;
friend class Declarations;
explicit Constant(const std::string& name, Type type,
const std::string& value)
: Value(Declarable::kConstant, type, name), value_(value) {}
@ -162,15 +185,14 @@ class Callable : public Declarable {
public:
static Callable* cast(Declarable* declarable) {
assert(declarable->IsMacro() || declarable->IsBuiltin() ||
declarable->IsRuntime());
declarable->IsRuntimeFunction());
return static_cast<Callable*>(declarable);
}
static const Callable* cast(const Declarable* declarable) {
assert(declarable->IsMacro() || declarable->IsBuiltin() ||
declarable->IsRuntime());
declarable->IsRuntimeFunction());
return static_cast<const Callable*>(declarable);
}
Scope* scope() const { return scope_; }
const std::string& name() const { return name_; }
const Signature& signature() const { return signature_; }
const NameVector& parameter_names() const {
@ -183,17 +205,12 @@ class Callable : public Declarable {
bool HasReturns() const { return returns_; }
protected:
Callable(Declarable::Kind kind, const std::string& name, Scope* scope,
Callable(Declarable::Kind kind, const std::string& name,
const Signature& signature)
: Declarable(kind),
name_(name),
scope_(scope),
signature_(signature),
returns_(0) {}
: Declarable(kind), name_(name), signature_(signature), returns_(0) {}
private:
std::string name_;
Scope* scope_;
Signature signature_;
size_t returns_;
};
@ -203,31 +220,30 @@ class Macro : public Callable {
DECLARE_DECLARABLE_BOILERPLATE(Macro, macro);
protected:
Macro(Declarable::Kind type, const std::string& name, Scope* scope,
Macro(Declarable::Kind type, const std::string& name,
const Signature& signature)
: Callable(type, name, scope, signature) {}
: Callable(type, name, signature) {}
private:
friend class Scope;
Macro(const std::string& name, Scope* scope, const Signature& signature)
: Macro(Declarable::kMacro, name, scope, signature) {}
friend class Declarations;
Macro(const std::string& name, const Signature& signature)
: Macro(Declarable::kMacro, name, signature) {}
};
class MacroList : public Declarable {
public:
DECLARE_DECLARABLE_BOILERPLATE(MacroList, macro_list);
const std::vector<std::unique_ptr<Macro>>& list() { return list_; }
Macro* AddMacro(std::unique_ptr<Macro> macro) {
Macro* result = macro.get();
list_.emplace_back(std::move(macro));
return result;
const std::vector<Macro*>& list() { return list_; }
Macro* AddMacro(Macro* macro) {
list_.emplace_back(macro);
return macro;
}
private:
friend class Scope;
friend class Declarations;
MacroList() : Declarable(Declarable::kMacroList) {}
std::vector<std::unique_ptr<Macro>> list_;
std::vector<Macro*> list_;
};
class Builtin : public Callable {
@ -240,22 +256,22 @@ class Builtin : public Callable {
bool IsFixedArgsJavaScript() const { return kind_ == kFixedArgsJavaScript; }
private:
friend class Scope;
Builtin(const std::string& name, Builtin::Kind kind, Scope* scope,
friend class Declarations;
Builtin(const std::string& name, Builtin::Kind kind,
const Signature& signature)
: Callable(Declarable::kBuiltin, name, scope, signature), kind_(kind) {}
: Callable(Declarable::kBuiltin, name, signature), kind_(kind) {}
Kind kind_;
};
class Runtime : public Callable {
class RuntimeFunction : public Callable {
public:
DECLARE_DECLARABLE_BOILERPLATE(Runtime, runtime);
DECLARE_DECLARABLE_BOILERPLATE(RuntimeFunction, runtime);
private:
friend class Scope;
Runtime(const std::string& name, Scope* scope, const Signature& signature)
: Callable(Declarable::kRuntime, name, scope, signature) {}
friend class Declarations;
RuntimeFunction(const std::string& name, const Signature& signature)
: Callable(Declarable::kRuntimeFunction, name, signature) {}
};
inline std::ostream& operator<<(std::ostream& os, const Callable& m) {
@ -275,8 +291,8 @@ inline std::ostream& operator<<(std::ostream& os, const Builtin& b) {
return os;
}
inline std::ostream& operator<<(std::ostream& os, const Runtime& b) {
os << "runtime " << b.signature().return_type << " " << b.name()
inline std::ostream& operator<<(std::ostream& os, const RuntimeFunction& b) {
os << "runtime function " << b.signature().return_type << " " << b.name()
<< b.signature().parameter_types;
return os;
}

View File

@ -48,12 +48,21 @@ void DeclarationVisitor::Visit(BuiltinDeclaration* decl) {
if (global_context_.verbose()) {
std::cout << "found declaration of builtin " << decl->name;
}
Scope* enclosing_scope = TopScope();
Signature signature = MakeSignature(decl->parameters, decl->return_type, {});
const bool javascript = decl->javascript_linkage;
const bool varargs = decl->parameters.has_varargs;
Builtin::Kind kind = !javascript ? Builtin::kStub
: varargs ? Builtin::kVarArgsJavaScript
: Builtin::kFixedArgsJavaScript;
Signature signature =
MakeSignature(decl->pos, decl->parameters, decl->return_type, {});
Builtin* builtin =
declarations()->DeclareBuiltin(decl->pos, decl->name, kind, signature);
CurrentCallableActivator activator(global_context_, builtin, decl);
DeclareParameterList(decl->pos, signature, {});
Scope* new_scope = new Scope(global_context_);
Scope::Activator s(new_scope);
if (signature.types().size() == 0 ||
!signature.types()[0].Is(CONTEXT_TYPE_STRING)) {
std::stringstream stream;
@ -66,8 +75,6 @@ void DeclarationVisitor::Visit(BuiltinDeclaration* decl) {
std::cout << decl->name << " with signature " << signature << std::endl;
}
const bool javascript = decl->javascript_linkage;
const bool varargs = decl->parameters.has_varargs;
if (varargs && !javascript) {
std::stringstream stream;
stream << "builtin " << decl->name
@ -87,50 +94,31 @@ void DeclarationVisitor::Visit(BuiltinDeclaration* decl) {
}
if (varargs) {
TopScope()->DeclareConstant(decl->pos, decl->parameters.arguments_variable,
GetTypeOracle().GetArgumentsType(),
"arguments");
declarations()->DeclareConstant(
decl->pos, decl->parameters.arguments_variable,
GetTypeOracle().GetArgumentsType(), "arguments");
}
Builtin::Kind kind = !javascript ? Builtin::kStub
: varargs ? Builtin::kVarArgsJavaScript
: Builtin::kFixedArgsJavaScript;
Builtin* builtin = enclosing_scope->DeclareBuiltin(
decl->pos, decl->name, kind, new_scope, signature);
defined_builtins_.push_back(builtin);
DeclareParameterList(decl->pos, signature, {});
CurrentCallActivator activator(global_context_, builtin);
Visit(decl->body);
}
void DeclarationVisitor::Visit(MacroDeclaration* decl) {
if (global_context_.verbose()) {
std::cout << "found declaration of macro " << decl->name;
}
Scope* enclosing_scope = TopScope();
Scope* new_scope = new Scope(global_context_);
Scope::Activator s(new_scope);
Signature signature = MakeSignature(decl->pos, decl->parameters,
decl->return_type, decl->labels);
PushControlSplit();
Macro* macro = declarations()->DeclareMacro(decl->pos, decl->name, signature);
CurrentCallableActivator activator(global_context_, macro, decl);
Signature signature =
MakeSignature(decl->parameters, decl->return_type, decl->labels);
DeclareParameterList(decl->pos, signature, decl->labels);
if (!signature.return_type.IsVoidOrNever()) {
TopScope()->DeclareVariable(decl->pos, kReturnValueVariable,
signature.return_type);
declarations()->DeclareVariable(decl->pos, kReturnValueVariable,
signature.return_type);
}
if (global_context_.verbose()) {
std::cout << " resulting in signature " << signature << "\n";
}
Macro* macro = enclosing_scope->DeclareMacro(decl->pos, decl->name, new_scope,
signature);
DeclareParameterList(decl->pos, signature, decl->labels);
CurrentCallActivator activator(global_context_, macro);
PushControlSplit();
Visit(decl->body);
auto changed_vars = PopControlSplit();
global_context_.AddControlSplitChangedVariables(decl, changed_vars);
}
@ -138,14 +126,14 @@ void DeclarationVisitor::Visit(MacroDeclaration* decl) {
void DeclarationVisitor::Visit(ReturnStatement* stmt) {
const Callable* callable = global_context_.GetCurrentCallable();
if (callable->IsMacro() && callable->HasReturnValue()) {
MarkVariableModified(
Variable::cast(LookupValue(stmt->pos, kReturnValueVariable)));
MarkVariableModified(Variable::cast(
declarations()->LookupValue(stmt->pos, kReturnValueVariable)));
}
}
void DeclarationVisitor::Visit(ForOfLoopStatement* stmt) {
// Scope for for iteration variable
Scope::Activator s(global_context_, stmt);
Declarations::NodeScopeActivator scope(declarations(), stmt);
Visit(stmt->var_declaration);
Visit(stmt->iterable);
if (stmt->begin) Visit(*stmt->begin);
@ -160,13 +148,14 @@ void DeclarationVisitor::Visit(TryCatchStatement* stmt) {
// Activate a new scope to declare catch handler labels, they should not be
// visible outside the catch.
{
Scope::Activator s(global_context_, stmt);
Declarations::NodeScopeActivator scope(declarations(), stmt);
// Declare catch labels
for (LabelBlock* block : stmt->label_blocks) {
Label* shared_label = TopScope()->DeclareLabel(stmt->pos, block->label);
Label* shared_label =
declarations()->DeclareLabel(stmt->pos, block->label);
{
Scope::Activator s(global_context_, block->body);
Declarations::NodeScopeActivator scope(declarations(), block->body);
if (block->parameters.has_varargs) {
std::stringstream stream;
stream << "cannot use ... for label parameters at "
@ -176,9 +165,10 @@ void DeclarationVisitor::Visit(TryCatchStatement* stmt) {
size_t i = 0;
for (auto p : block->parameters.names) {
shared_label->AddVariable(TopScope()->DeclareVariable(
shared_label->AddVariable(declarations()->DeclareVariable(
stmt->pos, p,
GetTypeOracle().GetType(block->parameters.types[i])));
declarations()->LookupType(stmt->pos,
block->parameters.types[i])));
++i;
}
}

View File

@ -8,6 +8,7 @@
#include <set>
#include <string>
#include "src/torque/declarations.h"
#include "src/torque/file-visitor.h"
#include "src/torque/global-context.h"
#include "src/torque/scope.h"
@ -21,11 +22,13 @@ namespace torque {
class DeclarationVisitor : public FileVisitor {
public:
explicit DeclarationVisitor(GlobalContext& global_context)
: FileVisitor(global_context) {
GetTypeOracle().RegisterTypeImpl(EXCEPTION_TYPE_STRING, "Label*", nullptr);
: FileVisitor(global_context),
scope_(declarations(), global_context.ast()->default_module()) {
declarations()->DeclareType(SourcePosition(), EXCEPTION_TYPE_STRING,
"Label*", nullptr);
}
void Visit(Ast* ast) { Visit(ast->GetDefaultModule()); }
void Visit(Ast* ast) { Visit(ast->default_module()); }
void Visit(Expression* expr);
void Visit(Statement* stmt);
@ -34,7 +37,7 @@ class DeclarationVisitor : public FileVisitor {
void Visit(ModuleDeclaration* decl) {
Module* saved_module = module_;
module_ = decl->GetModule();
Scope::Activator activator(module_->scope());
Declarations::NodeScopeActivator scope(declarations(), decl);
for (Declaration* child : decl->declarations) Visit(child);
module_ = saved_module;
}
@ -61,7 +64,7 @@ class DeclarationVisitor : public FileVisitor {
void Visit(CastExpression* expr) { Visit(expr->value); }
void Visit(ConvertExpression* expr) { Visit(expr->value); }
void Visit(BlockStatement* expr) {
Scope::Activator s(global_context_, expr);
Declarations::NodeScopeActivator scope(declarations(), expr);
for (Statement* stmt : expr->statements) Visit(stmt);
}
void Visit(ExpressionStatement* stmt) { Visit(stmt->expression); }
@ -70,8 +73,8 @@ class DeclarationVisitor : public FileVisitor {
void Visit(TypeDeclaration* decl) {
std::string generates_class_name =
decl->generates ? *decl->generates : decl->name;
GetTypeOracle().RegisterTypeImpl(decl->name, generates_class_name,
decl->extends ? &*decl->extends : nullptr);
declarations()->DeclareType(decl->pos, decl->name, generates_class_name,
decl->extends ? &*decl->extends : nullptr);
}
void Visit(ExternalBuiltinDeclaration* decl) {
@ -81,7 +84,7 @@ class DeclarationVisitor : public FileVisitor {
}
Signature signature =
MakeSignature(decl->parameters, decl->return_type, {});
MakeSignature(decl->pos, decl->parameters, decl->return_type, {});
if (signature.parameter_types.types.size() == 0 ||
!signature.parameter_types.types[0].Is(CONTEXT_TYPE_STRING)) {
@ -113,7 +116,7 @@ class DeclarationVisitor : public FileVisitor {
Builtin::Kind kind = !javascript ? Builtin::kStub
: varargs ? Builtin::kVarArgsJavaScript
: Builtin::kFixedArgsJavaScript;
TopScope()->DeclareBuiltin(decl->pos, decl->name, kind, nullptr, signature);
declarations()->DeclareBuiltin(decl->pos, decl->name, kind, signature);
}
void Visit(ExternalRuntimeDeclaration* decl) {
@ -121,8 +124,9 @@ class DeclarationVisitor : public FileVisitor {
std::cout << "found declaration of external runtime " << decl->name
<< " with signature ";
}
Type return_type = GetType(decl->return_type);
TypeVector parameter_types = GetTypeVector(decl->parameters.types);
Type return_type = declarations()->LookupType(decl->pos, decl->return_type);
TypeVector parameter_types =
GetTypeVector(decl->pos, decl->parameters.types);
if (parameter_types.size() == 0 ||
!parameter_types[0].Is(CONTEXT_TYPE_STRING)) {
std::stringstream stream;
@ -136,8 +140,8 @@ class DeclarationVisitor : public FileVisitor {
{parameter_types, decl->parameters.has_varargs},
return_type,
{}};
TopScope()->DeclareRuntime(decl->pos, decl->name, nullptr,
std::move(signature));
declarations()->DeclareRuntimeFunction(decl->pos, decl->name,
std::move(signature));
}
void Visit(ExternalMacroDeclaration* decl) {
@ -146,10 +150,10 @@ class DeclarationVisitor : public FileVisitor {
<< " with signature ";
}
Signature signature =
MakeSignature(decl->parameters, decl->return_type, decl->labels);
Signature signature = MakeSignature(decl->pos, decl->parameters,
decl->return_type, decl->labels);
TopScope()->DeclareMacro(decl->pos, decl->name, nullptr, signature);
declarations()->DeclareMacro(decl->pos, decl->name, signature);
if (decl->op) {
OperationHandler handler(
{decl->name, signature.parameter_types, signature.return_type});
@ -188,8 +192,8 @@ class DeclarationVisitor : public FileVisitor {
void Visit(VarDeclarationStatement* stmt) {
std::string variable_name = stmt->name;
Type type = GetType(stmt->type);
TopScope()->DeclareVariable(stmt->pos, variable_name, type);
Type type = declarations()->LookupType(stmt->pos, stmt->type);
declarations()->DeclareVariable(stmt->pos, variable_name, type);
if (global_context_.verbose()) {
std::cout << "declared variable " << variable_name << " with type "
<< type << "\n";
@ -204,14 +208,15 @@ class DeclarationVisitor : public FileVisitor {
}
void Visit(ConstDeclaration* decl) {
TopScope()->DeclareConstant(decl->pos, decl->name, GetType(decl->type),
decl->literal);
declarations()->DeclareConstant(
decl->pos, decl->name,
declarations()->LookupType(decl->pos, decl->type), decl->literal);
}
void Visit(LogicalOrExpression* expr) {
{
Scope::Activator s(global_context_, expr->left);
TopScope()->DeclareLabel(expr->pos, kFalseLabelName);
Declarations::NodeScopeActivator scope(declarations(), expr->left);
declarations()->DeclareLabel(expr->pos, kFalseLabelName);
Visit(expr->left);
}
Visit(expr->right);
@ -219,23 +224,23 @@ class DeclarationVisitor : public FileVisitor {
void Visit(LogicalAndExpression* expr) {
{
Scope::Activator s(global_context_, expr->left);
TopScope()->DeclareLabel(expr->pos, kTrueLabelName);
Declarations::NodeScopeActivator scope(declarations(), expr->left);
declarations()->DeclareLabel(expr->pos, kTrueLabelName);
Visit(expr->left);
}
Visit(expr->right);
}
void DeclareExpressionForBranch(Expression* node) {
Scope::Activator s(global_context_, node);
Declarations::NodeScopeActivator scope(declarations(), node);
// Conditional expressions can either explicitly return a bit
// type, or they can be backed by macros that don't return but
// take a true and false label. By declaring the labels before
// visiting the conditional expression, those label-based
// macro conditionals will be able to find them through normal
// label lookups.
TopScope()->DeclareLabel(node->pos, kTrueLabelName);
TopScope()->DeclareLabel(node->pos, kFalseLabelName);
declarations()->DeclareLabel(node->pos, kTrueLabelName);
declarations()->DeclareLabel(node->pos, kFalseLabelName);
Visit(node);
}
@ -258,7 +263,7 @@ class DeclarationVisitor : public FileVisitor {
}
void Visit(WhileStatement* stmt) {
Scope::Activator s(global_context_, stmt);
Declarations::NodeScopeActivator scope(declarations(), stmt);
DeclareExpressionForBranch(stmt->condition);
PushControlSplit();
Visit(stmt->body);
@ -279,7 +284,7 @@ class DeclarationVisitor : public FileVisitor {
void Visit(GotoStatement* expr) {}
void Visit(ForLoopStatement* stmt) {
Scope::Activator s(global_context_, stmt);
Declarations::NodeScopeActivator scope(declarations(), stmt);
if (stmt->var_declaration) Visit(*stmt->var_declaration);
PushControlSplit();
DeclareExpressionForBranch(stmt->test);
@ -353,7 +358,7 @@ class DeclarationVisitor : public FileVisitor {
void PushControlSplit() {
LiveAndChanged live_and_changed;
live_and_changed.live = global_context_.GetLiveTypeVariables();
live_and_changed.live = declarations()->GetLiveVariables();
live_and_changed_variables_.push_back(live_and_changed);
}
@ -365,7 +370,7 @@ class DeclarationVisitor : public FileVisitor {
void MarkLocationModified(Expression* location) {
if (IdentifierExpression* id = IdentifierExpression::cast(location)) {
const Value* value = LookupValue(id->pos, id->name);
const Value* value = declarations()->LookupValue(id->pos, id->name);
if (value->IsVariable()) {
const Variable* variable = Variable::cast(value);
bool was_live = MarkVariableModified(variable);
@ -396,23 +401,24 @@ class DeclarationVisitor : public FileVisitor {
auto name_iterator = signature.parameter_names.begin();
for (auto t : signature.types()) {
const std::string& name(*name_iterator++);
TopScope()->DeclareParameter(pos, name,
GetParameterVariableFromName(name), t);
declarations()->DeclareParameter(pos, name,
GetParameterVariableFromName(name), t);
}
if (labels) {
for (auto label : *labels) {
auto label_params = GetTypeVector(label.types);
Label* new_label = TopScope()->DeclareLabel(pos, label.name);
auto label_params = GetTypeVector(pos, label.types);
Label* new_label = declarations()->DeclareLabel(pos, label.name);
size_t i = 0;
for (auto var_type : label_params) {
std::string var_name = label.name + std::to_string(i++);
new_label->AddVariable(
TopScope()->DeclareVariable(pos, var_name, var_type));
declarations()->DeclareVariable(pos, var_name, var_type));
}
}
}
}
Declarations::NodeScopeActivator scope_;
std::vector<Builtin*> defined_builtins_;
std::vector<LiveAndChanged> live_and_changed_variables_;
};

209
src/torque/declarations.cc Normal file
View File

@ -0,0 +1,209 @@
// 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"
namespace v8 {
namespace internal {
namespace torque {
Scope* Declarations::GetNodeScope(const AstNode* node) {
auto i = node_scopes_.find(node);
if (i != node_scopes_.end()) return i->second;
Scope* result = chain_.NewScope();
node_scopes_[node] = result;
return result;
}
void Declarations::CheckAlreadyDeclared(SourcePosition pos,
const std::string& name,
const char* new_type) {
auto i = chain_.ShallowLookup(name);
if (i != nullptr) {
std::stringstream s;
s << "cannot redeclare " << name << " (type " << new_type << ") at "
<< PositionAsString(pos) << std::endl;
ReportError(s.str());
}
}
Type Declarations::LookupType(SourcePosition pos, const std::string& name) {
Declarable* raw = Lookup(pos, name);
if (!raw->IsTypeImpl()) {
std::stringstream s;
s << "declaration \"" << name << "\" is not a Type at "
<< PositionAsString(pos);
ReportError(s.str());
}
return Type(TypeImpl::cast(raw));
}
Value* Declarations::LookupValue(SourcePosition pos, const std::string& name) {
Declarable* d = Lookup(pos, name);
if (!d->IsValue()) {
std::stringstream s;
s << "declaration \"" << name << "\" is not a Value at "
<< PositionAsString(pos);
ReportError(s.str());
}
return Value::cast(d);
}
Macro* Declarations::LookupMacro(SourcePosition pos, const std::string& name,
const TypeVector& types) {
Declarable* declarable = Lookup(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;
}
}
}
}
std::stringstream stream;
stream << "macro " << name << " with parameter types " << types
<< " referenced at " << PositionAsString(pos) << " is not defined";
ReportError(stream.str());
return nullptr;
}
Builtin* Declarations::LookupBuiltin(const SourcePosition& pos,
const std::string& name) {
Declarable* declarable = Lookup(name);
if (declarable != nullptr) {
if (declarable->IsBuiltin()) {
return Builtin::cast(declarable);
}
ReportError(name + " referenced at " + PositionAsString(pos) +
" is not a builtin");
}
ReportError(std::string("builtin ") + name + " referenced at " +
PositionAsString(pos) + " is not defined");
return nullptr;
}
Type Declarations::DeclareType(SourcePosition pos, const std::string& name,
const std::string& generated,
const std::string* parent) {
CheckAlreadyDeclared(pos, name, "type");
TypeImpl* parent_type = nullptr;
if (parent != nullptr) {
Declarable* maybe_parent_type = Lookup(*parent);
if (maybe_parent_type == nullptr) {
std::stringstream s;
s << "cannot find parent type \"" << *parent << "\" at "
<< PositionAsString(pos);
ReportError(s.str());
}
if (!maybe_parent_type->IsTypeImpl()) {
std::stringstream s;
s << "parent \"" << *parent << "\" of type \"" << name << "\""
<< " is not a type "
<< " at " << PositionAsString(pos);
ReportError(s.str());
}
parent_type = TypeImpl::cast(maybe_parent_type);
}
TypeImpl* result = new TypeImpl(parent_type, name, generated);
Declare(name, std::unique_ptr<Declarable>(result));
return Type(result);
}
Label* Declarations::DeclareLabel(SourcePosition pos, const std::string& name) {
CheckAlreadyDeclared(pos, name, "label");
Label* result = new Label(name);
Declare(name, std::unique_ptr<Declarable>(result));
return result;
}
Macro* Declarations::DeclareMacro(SourcePosition pos, 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 at "
<< PositionAsString(pos);
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 << PositionAsString(pos);
ReportError(s.str());
}
}
return macro_list->AddMacro(new Macro(name, signature));
}
Builtin* Declarations::DeclareBuiltin(SourcePosition pos,
const std::string& name,
Builtin::Kind kind,
const Signature& signature) {
CheckAlreadyDeclared(pos, name, "builtin");
Builtin* result = new Builtin(name, kind, signature);
Declare(name, std::unique_ptr<Declarable>(result));
return result;
}
RuntimeFunction* Declarations::DeclareRuntimeFunction(
SourcePosition pos, const std::string& name, const Signature& signature) {
CheckAlreadyDeclared(pos, name, "runtime function");
RuntimeFunction* result = new RuntimeFunction(name, signature);
Declare(name, std::unique_ptr<Declarable>(result));
return result;
}
Variable* Declarations::DeclareVariable(SourcePosition pos,
const std::string& var, Type type) {
std::string name(var + std::to_string(GetNextUniqueDeclarationNumber()));
CheckAlreadyDeclared(pos, var, "variable");
Variable* result = new Variable(var, name, type);
Declare(var, std::unique_ptr<Declarable>(result));
return result;
}
Parameter* Declarations::DeclareParameter(SourcePosition pos,
const std::string& name,
const std::string& var_name,
Type type) {
CheckAlreadyDeclared(pos, name, "parameter");
Parameter* result = new Parameter(name, type, var_name);
Declare(name, std::unique_ptr<Declarable>(result));
return result;
}
Label* Declarations::DeclarePrivateLabel(SourcePosition pos,
const std::string& raw_name) {
std::string name =
raw_name + "_" + std::to_string(GetNextUniqueDeclarationNumber());
CheckAlreadyDeclared(pos, name, "label");
Label* result = new Label(name);
Declare(name, std::unique_ptr<Declarable>(result));
return result;
}
void Declarations::DeclareConstant(SourcePosition pos, const std::string& name,
Type type, const std::string& value) {
CheckAlreadyDeclared(pos, name, "constant, parameter or arguments");
Constant* result = new Constant(name, type, value);
Declare(name, std::unique_ptr<Declarable>(result));
}
} // namespace torque
} // namespace internal
} // namespace v8

114
src/torque/declarations.h Normal file
View File

@ -0,0 +1,114 @@
// 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_DECLARATIONS_H_
#define V8_TORQUE_DECLARATIONS_H_
#include <string>
#include "src/torque/declarable.h"
#include "src/torque/scope.h"
namespace v8 {
namespace internal {
namespace torque {
class Declarations {
public:
explicit Declarations(SourceFileMap* source_file_map)
: source_file_map_(source_file_map), unique_declaration_number_(0) {}
Declarable* Lookup(const std::string& name) { return chain_.Lookup(name); }
Declarable* Lookup(SourcePosition pos, const std::string& name) {
Declarable* d = Lookup(name);
if (d == nullptr) {
std::stringstream s;
s << "cannot find \"" << name << "\" at " << PositionAsString(pos);
ReportError(s.str());
}
return d;
}
Type LookupType(SourcePosition pos, const std::string& name);
Value* LookupValue(SourcePosition pos, const std::string& name);
Macro* LookupMacro(SourcePosition pos, const std::string& name,
const TypeVector& types);
Builtin* LookupBuiltin(const SourcePosition& pos, const std::string& name);
Type DeclareType(SourcePosition pos, const std::string& name,
const std::string& generated,
const std::string* parent = nullptr);
Label* DeclareLabel(SourcePosition pos, const std::string& name);
Macro* DeclareMacro(SourcePosition pos, const std::string& name,
const Signature& signature);
Builtin* DeclareBuiltin(SourcePosition pos, const std::string& name,
Builtin::Kind kind, const Signature& signature);
RuntimeFunction* DeclareRuntimeFunction(SourcePosition pos,
const std::string& name,
const Signature& signature);
Variable* DeclareVariable(SourcePosition pos, const std::string& var,
Type type);
Parameter* DeclareParameter(SourcePosition pos, const std::string& name,
const std::string& mangled_name, Type type);
Label* DeclarePrivateLabel(SourcePosition pos, const std::string& name);
void DeclareConstant(SourcePosition pos, const std::string& name, Type type,
const std::string& value);
std::set<const Variable*> GetLiveVariables() {
return chain_.GetLiveVariables();
}
std::string PositionAsString(SourcePosition pos) {
return source_file_map_->PositionAsString(pos);
}
class NodeScopeActivator;
private:
Scope* GetNodeScope(const AstNode* node);
void Declare(const std::string& name, std::unique_ptr<Declarable> d) {
Declarable* ptr = d.get();
declarables_.emplace_back(std::move(d));
chain_.Declare(name, ptr);
}
int GetNextUniqueDeclarationNumber() { return unique_declaration_number_++; }
void CheckAlreadyDeclared(SourcePosition pos, const std::string& name,
const char* new_type);
SourceFileMap* source_file_map_;
int unique_declaration_number_;
ScopeChain chain_;
std::vector<std::unique_ptr<Declarable>> declarables_;
std::map<const AstNode*, Scope*> node_scopes_;
};
class Declarations::NodeScopeActivator {
public:
NodeScopeActivator(Declarations* declarations, AstNode* node)
: activator_(declarations->GetNodeScope(node)) {}
private:
Scope::Activator activator_;
};
} // namespace torque
} // namespace internal
} // namespace v8
#endif // V8_TORQUE_DECLARATIONS_H_

View File

@ -10,18 +10,66 @@ namespace v8 {
namespace internal {
namespace torque {
Signature FileVisitor::MakeSignature(const ParameterList& parameters,
Signature FileVisitor::MakeSignature(SourcePosition pos,
const ParameterList& parameters,
const std::string& return_type,
const LabelAndTypesVector& labels) {
LabelDeclarationVector definition_vector;
for (auto label : labels) {
LabelDeclaration def = {label.name, GetTypeVector(label.types)};
LabelDeclaration def = {label.name, GetTypeVector(pos, label.types)};
definition_vector.push_back(def);
}
Signature result{parameters.names,
{GetTypeVector(parameters.types), parameters.has_varargs},
GetType(return_type),
definition_vector};
Signature result{
parameters.names,
{GetTypeVector(pos, parameters.types), parameters.has_varargs},
declarations()->LookupType(pos, return_type),
definition_vector};
return result;
}
Callable* FileVisitor::LookupCall(SourcePosition pos, const std::string& name,
const TypeVector& parameter_types) {
Callable* result = nullptr;
Declarable* declarable = declarations()->Lookup(pos, name);
if (declarable->IsBuiltin()) {
result = Builtin::cast(declarable);
} else if (declarable->IsRuntimeFunction()) {
result = RuntimeFunction::cast(declarable);
} else if (declarable->IsMacroList()) {
for (auto& m : MacroList::cast(declarable)->list()) {
if (GetTypeOracle().IsCompatibleSignature(m->signature().parameter_types,
parameter_types)) {
if (result != nullptr) {
std::stringstream stream;
stream << "multiple matching matching parameter list for macro "
<< name << ": (" << parameter_types << ") and ("
<< result->signature().parameter_types << ") at "
<< PositionAsString(pos);
ReportError(stream.str());
}
result = m;
}
}
if (result == nullptr) {
std::stringstream stream;
stream << "no matching matching parameter list for macro " << name
<< ": call parameters were (" << parameter_types << ") at "
<< PositionAsString(pos);
ReportError(stream.str());
}
}
size_t caller_size = parameter_types.size();
size_t callee_size = result->signature().types().size();
if (caller_size != callee_size &&
!result->signature().parameter_types.var_args) {
std::stringstream stream;
stream << "parameter count mismatch calling " << *result << ": expected "
<< std::to_string(callee_size) << ", found "
<< std::to_string(caller_size);
ReportError(stream.str());
}
return result;
}

View File

@ -22,22 +22,20 @@ class FileVisitor {
public:
explicit FileVisitor(GlobalContext& global_context)
: global_context_(global_context),
module_(global_context.GetDefaultModule()) {
global_context_.PushScope(module_->scope());
}
declarations_(global_context.declarations()),
module_(global_context.GetDefaultModule()) {}
Type GetType(const std::string& s) { return GetTypeOracle().GetType(s); }
TypeVector GetTypeVector(const std::vector<std::string>& v) {
TypeVector GetTypeVector(SourcePosition pos,
const std::vector<std::string>& v) {
TypeVector result;
for (const std::string& s : v) {
result.push_back(GetType(s));
result.push_back(declarations()->LookupType(pos, s));
}
return result;
}
Scope* TopScope() { return global_context_.TopScope(); }
Ast* ast() { return global_context_.ast(); }
Declarations* declarations() { return global_context_.declarations(); }
protected:
static constexpr const char* kTrueLabelName = "True";
@ -51,110 +49,23 @@ class FileVisitor {
TypeOracle& GetTypeOracle() { return global_context_.GetTypeOracle(); }
bool IsValueDeclared(const std::string& id) {
return global_context_.Lookup(id) != nullptr;
}
Value* LookupValue(SourcePosition pos, const std::string& id) {
Declarable* declarable = global_context_.Lookup(id);
if (declarable != nullptr) {
if (declarable->IsValue()) {
return Value::cast(declarable);
}
ReportError(id + " referenced at " + PositionAsString(pos) +
" is not a variable, parameter or verbatim");
}
ReportError(std::string("identifier ") + id + " referenced at " +
PositionAsString(pos) + " is not defined");
return nullptr;
}
Callable* LookupCall(SourcePosition pos, const std::string& name,
const TypeVector& parameter_types) {
Callable* result = nullptr;
Declarable* declarable = global_context_.Lookup(name);
if (declarable != nullptr) {
if (declarable->IsBuiltin()) {
result = Builtin::cast(declarable);
} else if (declarable->IsRuntime()) {
result = Runtime::cast(declarable);
} else if (declarable->IsMacroList()) {
for (auto& m : MacroList::cast(declarable)->list()) {
if (GetTypeOracle().IsCompatibleSignature(
m->signature().parameter_types, parameter_types)) {
result = m.get();
break;
}
}
}
}
if (result == nullptr) {
std::stringstream stream;
stream << "cannot find macro, builtin or runtime call " << name
<< " matching parameter types " << parameter_types;
ReportError(stream.str());
}
size_t caller_size = parameter_types.size();
size_t callee_size = result->signature().types().size();
if (caller_size != callee_size &&
!result->signature().parameter_types.var_args) {
std::stringstream stream;
stream << "parameter count mismatch calling " << *result << ": expected "
<< std::to_string(callee_size) << ", found "
<< std::to_string(caller_size);
ReportError(stream.str());
}
return result;
}
Macro* LookupMacro(SourcePosition pos, const std::string& name,
const TypeVector& types) {
Declarable* declarable = global_context_.Lookup(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.get();
}
}
}
}
std::stringstream stream;
stream << "macro " << name << " with parameter types " << types
<< " referenced at " << PositionAsString(pos) << " is not defined";
ReportError(stream.str());
return nullptr;
}
Builtin* LookupBuiltin(const SourcePosition& pos, const std::string& name) {
Declarable* declarable = global_context_.Lookup(name);
if (declarable != nullptr) {
if (declarable->IsBuiltin()) {
return Builtin::cast(declarable);
}
ReportError(name + " referenced at " + PositionAsString(pos) +
" is not a builtin");
}
ReportError(std::string("builtin ") + name + " referenced at " +
PositionAsString(pos) + " is not defined");
return nullptr;
}
std::string GetParameterVariableFromName(const std::string& name) {
return std::string("p_") + name;
}
std::string PositionAsString(SourcePosition pos) {
return global_context_.PositionAsString(pos);
return global_context_.ast()->source_file_map()->PositionAsString(pos);
}
Signature MakeSignature(const ParameterList& parameters,
Callable* LookupCall(SourcePosition pos, const std::string& name,
const TypeVector& parameter_types);
Signature MakeSignature(SourcePosition pos, const ParameterList& parameters,
const std::string& return_type,
const LabelAndTypesVector& labels);
GlobalContext& global_context_;
Declarations* declarations_;
Callable* current_callable_;
Module* module_;
};

View File

@ -8,6 +8,7 @@
#include "src/torque/TorqueLexer.h"
#include "src/torque/TorqueParser.h"
#include "src/torque/declarable.h"
#include "src/torque/declarations.h"
#include "src/torque/scope.h"
#include "src/torque/type-oracle.h"
@ -21,19 +22,15 @@ class TypeOracle;
class Module {
public:
Module(const std::string& name, GlobalContext& context) : name_(name) {
scope_ = new Scope(context);
}
explicit Module(const std::string& name) : name_(name) {}
const std::string& name() const { return name_; }
std::ostream& source_stream() { return source_stream_; }
std::ostream& header_stream() { return header_stream_; }
std::string source() { return source_stream_.str(); }
std::string header() { return header_stream_.str(); }
Scope* scope() { return scope_; }
private:
std::string name_;
Scope* scope_;
std::stringstream header_stream_;
std::stringstream source_stream_;
};
@ -66,8 +63,9 @@ class GlobalContext {
public:
explicit GlobalContext(Ast ast)
: verbose_(false),
next_scope_number_(0),
next_label_number_(0),
declarations_(ast.source_file_map()),
type_oracle_(&declarations_),
default_module_(GetModule("base")),
ast_(std::move(ast)) {}
Module* GetDefaultModule() { return default_module_; }
@ -76,55 +74,17 @@ class GlobalContext {
if (i != modules_.end()) {
return i->second.get();
}
Module* module = new Module(name, *this);
Module* module = new Module(name);
modules_[name] = std::unique_ptr<Module>(module);
return module;
}
int GetNextScopeNumber() { return next_scope_number_++; }
int GetNextLabelNumber() { return next_label_number_++; }
const std::map<std::string, std::unique_ptr<Module>>& GetModules() const {
return modules_;
}
Scope* GetParserRuleContextScope(const AstNode* context) {
auto i = context_scopes_.find(context);
if (i != context_scopes_.end()) return i->second;
Scope* new_scope = new Scope(*this);
context_scopes_[context] = new_scope;
return new_scope;
}
Scope* TopScope() const { return current_scopes_.back(); }
Declarable* Lookup(const std::string& name) const {
auto e = current_scopes_.rend();
auto c = current_scopes_.rbegin();
while (c != e) {
Declarable* result = (*c)->Lookup(name);
if (result != nullptr) return result;
++c;
}
return nullptr;
}
void RegisterScope(Scope* scope) {
scopes_.emplace_back(std::unique_ptr<Scope>(scope));
}
void PushScope(Scope* scope) { current_scopes_.push_back(scope); }
void PopScope() { current_scopes_.pop_back(); }
std::set<const Variable*> GetLiveTypeVariables() {
std::set<const Variable*> result;
for (auto scope : current_scopes_) {
scope->AddLiveVariables(result);
}
return result;
}
void SetVerbose() { verbose_ = true; }
bool verbose() const { return verbose_; }
@ -144,7 +104,7 @@ class GlobalContext {
control_split_changed_variables_[node].insert(var);
}
friend class CurrentCallActivator;
friend class CurrentCallableActivator;
friend class BreakContinueActivator;
TypeOracle& GetTypeOracle() { return type_oracle_; }
@ -157,45 +117,39 @@ class GlobalContext {
std::map<std::string, std::vector<OperationHandler>> op_handlers_;
void PrintScopeChain() {
for (auto s : current_scopes_) {
s->Print();
}
}
std::string PositionAsString(SourcePosition pos) {
return ast_.PositionAsString(pos);
return declarations()->PositionAsString(pos);
}
Declarations* declarations() { return &declarations_; }
Ast* ast() { return &ast_; }
private:
bool verbose_;
int next_scope_number_;
int next_label_number_;
std::map<std::string, std::unique_ptr<Module>> modules_;
std::vector<std::unique_ptr<Scope>> scopes_;
Module* default_module_;
std::vector<Scope*> current_scopes_;
std::vector<std::pair<Label*, Label*>> break_continue_stack_;
Declarations declarations_;
TypeOracle type_oracle_;
std::map<std::string, std::unique_ptr<Module>> modules_;
Module* default_module_;
std::vector<std::pair<Label*, Label*>> break_continue_stack_;
Callable* current_callable_;
std::map<const AstNode*, std::set<const Variable*>>
control_split_changed_variables_;
std::map<const AstNode*, Scope*> context_scopes_;
Ast ast_;
};
class CurrentCallActivator {
class CurrentCallableActivator {
public:
CurrentCallActivator(GlobalContext& context, Callable* callable)
: context_(context) {
CurrentCallableActivator(GlobalContext& context, Callable* callable,
Declaration* decl)
: context_(context), scope_activator_(context.declarations(), decl) {
context_.current_callable_ = callable;
}
~CurrentCallActivator() { context_.current_callable_ = nullptr; }
~CurrentCallableActivator() { context_.current_callable_ = nullptr; }
private:
GlobalContext& context_;
Declarations::NodeScopeActivator scope_activator_;
};
class BreakContinueActivator {

View File

@ -114,7 +114,7 @@ void ImplementationVisitor::Visit(ModuleDeclaration* decl) {
Module* saved_module = module_;
module_ = module;
Scope::Activator activator(module_->scope());
Declarations::NodeScopeActivator scope(declarations(), decl);
for (auto& child : decl->declarations) Visit(child);
module_ = saved_module;
@ -130,13 +130,12 @@ void ImplementationVisitor::Visit(ModuleDeclaration* decl) {
}
void ImplementationVisitor::Visit(MacroDeclaration* decl) {
Signature signature =
MakeSignature(decl->parameters, decl->return_type, decl->labels);
Signature signature = MakeSignature(decl->pos, decl->parameters,
decl->return_type, decl->labels);
const TypeVector& list = signature.types();
Macro* macro = LookupMacro(decl->pos, decl->name, list);
Macro* macro = declarations()->LookupMacro(decl->pos, decl->name, list);
CurrentCallActivator activator(global_context_, macro);
Scope::Activator activate(macro->scope());
CurrentCallableActivator activator(global_context_, macro, decl);
header_out() << " ";
GenerateMacroFunctionDeclaration(header_out(), decl->pos, "", macro);
@ -159,13 +158,12 @@ void ImplementationVisitor::Visit(MacroDeclaration* decl) {
result_var =
GenerateVariableDeclaration(decl, kReturnValueVariable, {}, init);
}
Label* macro_end = TopScope()->DeclareLabel(decl->pos, "macro_end");
Label* macro_end = declarations()->DeclareLabel(decl->pos, "macro_end");
GenerateLabelDefinition(macro_end, decl);
Type result = Visit(decl->body);
if (result.IsNever()) {
if (!macro->signature().return_type.IsNever() &&
!global_context_.GetCurrentCallable()->HasReturns()) {
if (!macro->signature().return_type.IsNever() && !macro->HasReturns()) {
std::stringstream s;
s << "macro " << decl->name
<< " that never returns must have return type never at "
@ -205,12 +203,12 @@ void ImplementationVisitor::Visit(MacroDeclaration* decl) {
void ImplementationVisitor::Visit(BuiltinDeclaration* decl) {
source_out() << "TF_BUILTIN(" << decl->name << ", "
<< GetDSLAssemblerName(CurrentModule()) << ") {" << std::endl;
Builtin* builtin = LookupBuiltin(decl->pos, decl->name);
CurrentCallActivator activator(global_context_, builtin);
Scope::Activator activate(builtin->scope());
Builtin* builtin = declarations()->LookupBuiltin(decl->pos, decl->name);
CurrentCallableActivator activator(global_context_, builtin, decl);
// Context
const Value* val = LookupValue(decl->pos, decl->parameters.names[0]);
const Value* val =
declarations()->LookupValue(decl->pos, decl->parameters.names[0]);
GenerateIndent();
source_out() << "TNode<Context> " << val->GetValueForDeclaration()
<< " = UncheckedCast<Context>(Parameter("
@ -222,8 +220,8 @@ void ImplementationVisitor::Visit(BuiltinDeclaration* decl) {
size_t first = 1;
if (builtin->IsVarArgsJavaScript()) {
assert(decl->parameters.has_varargs);
Constant* arguments = Constant::cast(
LookupValue(decl->pos, decl->parameters.arguments_variable));
Constant* arguments = Constant::cast(declarations()->LookupValue(
decl->pos, decl->parameters.arguments_variable));
std::string arguments_name = arguments->GetValueForDeclaration();
GenerateIndent();
source_out()
@ -233,7 +231,8 @@ void ImplementationVisitor::Visit(BuiltinDeclaration* decl) {
source_out() << "CodeStubArguments arguments_impl(this, "
"ChangeInt32ToIntPtr(argc));"
<< std::endl;
const Value* receiver = LookupValue(decl->pos, decl->parameters.names[1]);
const Value* receiver =
declarations()->LookupValue(decl->pos, decl->parameters.names[1]);
GenerateIndent();
source_out() << "TNode<Object> " << receiver->GetValueForDeclaration()
<< " = arguments_impl.GetReceiver();" << std::endl;
@ -301,14 +300,16 @@ VisitResult ImplementationVisitor::Visit(ConditionalExpression* expr) {
{
ScopedIndent indent(this);
Scope::Activator s(global_context_, expr->condition);
Declarations::NodeScopeActivator scope(declarations(), expr->condition);
Label* true_label = Label::cast(LookupValue(expr->pos, kTrueLabelName));
Label* true_label =
Label::cast(declarations()->LookupValue(expr->pos, kTrueLabelName));
GenerateLabelDefinition(true_label);
Label* false_label = Label::cast(LookupValue(expr->pos, kFalseLabelName));
Label* false_label =
Label::cast(declarations()->LookupValue(expr->pos, kFalseLabelName));
GenerateLabelDefinition(false_label);
Label* done_label =
TopScope()->DeclarePrivateLabel(expr->pos, kDoneLabelName);
declarations()->DeclarePrivateLabel(expr->pos, kDoneLabelName);
GenerateLabelDefinition(done_label, expr);
VisitResult condition_result = Visit(expr->condition);
@ -335,12 +336,14 @@ VisitResult ImplementationVisitor::Visit(ConditionalExpression* expr) {
VisitResult ImplementationVisitor::Visit(LogicalOrExpression* expr) {
{
Scope::Activator s(global_context_, expr->left);
Label* false_label = Label::cast(LookupValue(expr->pos, kFalseLabelName));
Declarations::NodeScopeActivator scope(declarations(), expr->left);
Label* false_label =
Label::cast(declarations()->LookupValue(expr->pos, kFalseLabelName));
GenerateLabelDefinition(false_label);
VisitResult left_result = Visit(expr->left);
if (left_result.type().IsBit()) {
Label* true_label = Label::cast(LookupValue(expr->pos, kTrueLabelName));
Label* true_label =
Label::cast(declarations()->LookupValue(expr->pos, kTrueLabelName));
GenerateIndent();
source_out() << "GotoIf(" << left_result.variable() << ", "
<< true_label->GetValueForRead() << ");" << std::endl;
@ -353,12 +356,14 @@ VisitResult ImplementationVisitor::Visit(LogicalOrExpression* expr) {
VisitResult ImplementationVisitor::Visit(LogicalAndExpression* expr) {
{
Scope::Activator s(global_context_, expr->left);
Label* true_label = Label::cast(LookupValue(expr->pos, kTrueLabelName));
Declarations::NodeScopeActivator scope(declarations(), expr->left);
Label* true_label =
Label::cast(declarations()->LookupValue(expr->pos, kTrueLabelName));
GenerateLabelDefinition(true_label);
VisitResult left_result = Visit(expr->left);
if (left_result.type().IsBit()) {
Label* false_label = Label::cast(LookupValue(expr->pos, kFalseLabelName));
Label* false_label =
Label::cast(declarations()->LookupValue(expr->pos, kFalseLabelName));
GenerateIndent();
source_out() << "GotoIfNot(" << left_result.variable() << ", "
<< false_label->GetValueForRead() << ");" << std::endl;
@ -409,13 +414,16 @@ VisitResult ImplementationVisitor::Visit(NumberLiteralExpression* expr) {
// TODO(tebbi): Do not silently loose precision; support 64bit literals.
double d = std::stod(expr->number.c_str());
int32_t i = static_cast<int32_t>(d);
Type result_type = GetTypeOracle().GetType(CONST_FLOAT64_TYPE_STRING);
Type result_type =
declarations()->LookupType(expr->pos, CONST_FLOAT64_TYPE_STRING);
if (i == d) {
if (Internals::IsValidSmi(i)) {
if (sizeof(void*) == sizeof(double) && ((i >> 30) != (i >> 31))) {
result_type = GetTypeOracle().GetType(CONST_INT32_TYPE_STRING);
result_type =
declarations()->LookupType(expr->pos, CONST_INT32_TYPE_STRING);
} else {
result_type = GetTypeOracle().GetType(CONST_INT31_TYPE_STRING);
result_type =
declarations()->LookupType(expr->pos, CONST_INT31_TYPE_STRING);
}
}
}
@ -436,13 +444,15 @@ VisitResult ImplementationVisitor::Visit(CastExpression* expr) {
Arguments args;
args.parameters = {Visit(expr->value)};
args.labels = LabelsFromIdentifiers(expr->pos, {expr->otherwise});
return GenerateOperation(expr->pos, "cast<>", args, GetType(expr->type));
return GenerateOperation(expr->pos, "cast<>", args,
declarations()->LookupType(expr->pos, expr->type));
}
VisitResult ImplementationVisitor::Visit(ConvertExpression* expr) {
Arguments args;
args.parameters = {Visit(expr->value)};
return GenerateOperation(expr->pos, "convert<>", args, GetType(expr->type));
return GenerateOperation(expr->pos, "convert<>", args,
declarations()->LookupType(expr->pos, expr->type));
}
Type ImplementationVisitor::Visit(GotoStatement* stmt) {
@ -477,17 +487,20 @@ Type ImplementationVisitor::Visit(IfStatement* stmt) {
Label* true_label = nullptr;
Label* false_label = nullptr;
{
Scope::Activator activate(global_context_, &*stmt->condition);
true_label = Label::cast(LookupValue(stmt->pos, kTrueLabelName));
Declarations::NodeScopeActivator scope(declarations(), &*stmt->condition);
true_label =
Label::cast(declarations()->LookupValue(stmt->pos, kTrueLabelName));
GenerateLabelDefinition(true_label);
false_label = Label::cast(LookupValue(stmt->pos, kFalseLabelName));
false_label =
Label::cast(declarations()->LookupValue(stmt->pos, kFalseLabelName));
GenerateLabelDefinition(false_label, !has_else ? stmt : nullptr);
}
Label* done_label = nullptr;
bool live = false;
if (has_else) {
done_label = TopScope()->DeclarePrivateLabel(stmt->pos, "if_done_label");
done_label =
declarations()->DeclarePrivateLabel(stmt->pos, "if_done_label");
GenerateLabelDefinition(done_label, stmt);
} else {
done_label = false_label;
@ -511,19 +524,22 @@ Type ImplementationVisitor::Visit(WhileStatement* stmt) {
Label* body_label = nullptr;
Label* exit_label = nullptr;
{
Scope::Activator s(global_context_, stmt->condition);
body_label = Label::cast(LookupValue(stmt->pos, kTrueLabelName));
Declarations::NodeScopeActivator scope(declarations(), stmt->condition);
body_label =
Label::cast(declarations()->LookupValue(stmt->pos, kTrueLabelName));
GenerateLabelDefinition(body_label);
exit_label = Label::cast(LookupValue(stmt->pos, kFalseLabelName));
exit_label =
Label::cast(declarations()->LookupValue(stmt->pos, kFalseLabelName));
GenerateLabelDefinition(exit_label);
}
Label* header_label = TopScope()->DeclarePrivateLabel(stmt->pos, "header");
Label* header_label =
declarations()->DeclarePrivateLabel(stmt->pos, "header");
GenerateLabelDefinition(header_label, stmt);
GenerateLabelGoto(header_label);
GenerateLabelBind(header_label);
Scope::Activator s(global_context_, stmt->body);
Declarations::NodeScopeActivator scope(declarations(), stmt->body);
BreakContinueActivator activator(global_context_, exit_label, header_label);
GenerateExpressionBranch(stmt->condition, {body_label, exit_label},
@ -534,7 +550,7 @@ Type ImplementationVisitor::Visit(WhileStatement* stmt) {
}
Type ImplementationVisitor::Visit(BlockStatement* block) {
Scope::Activator s(global_context_, block);
Declarations::NodeScopeActivator scope(declarations(), block);
ScopedIndent indent(this);
Type type = GetTypeOracle().GetVoidType();
for (Statement* s : block->statements) {
@ -562,9 +578,10 @@ Type ImplementationVisitor::Visit(ReturnStatement* stmt) {
<< PositionAsString(stmt->pos);
ReportError(s.str());
}
Label* end = current_callable->IsMacro()
? Label::cast(LookupValue(stmt->pos, "macro_end"))
: nullptr;
Label* end =
current_callable->IsMacro()
? Label::cast(declarations()->LookupValue(stmt->pos, "macro_end"))
: nullptr;
if (current_callable->HasReturnValue()) {
if (!stmt->value) {
std::stringstream s;
@ -578,8 +595,8 @@ Type ImplementationVisitor::Visit(ReturnStatement* stmt) {
stmt->pos, current_callable->signature().return_type,
expression_result);
if (current_callable->IsMacro()) {
Variable* var =
Variable::cast(LookupValue(stmt->pos, kReturnValueVariable));
Variable* var = Variable::cast(
declarations()->LookupValue(stmt->pos, kReturnValueVariable));
GenerateAssignToVariable(stmt->pos, var, return_result);
GenerateLabelGoto(end);
} else if (current_callable->IsBuiltin()) {
@ -610,7 +627,7 @@ Type ImplementationVisitor::Visit(ReturnStatement* stmt) {
}
Type ImplementationVisitor::Visit(ForOfLoopStatement* stmt) {
Scope::Activator s(global_context_, stmt);
Declarations::NodeScopeActivator scope(declarations(), stmt);
VisitResult expression_result = Visit(stmt->iterable);
VisitResult begin =
@ -621,12 +638,12 @@ Type ImplementationVisitor::Visit(ForOfLoopStatement* stmt) {
: GenerateOperation(stmt->pos, ".length",
{{expression_result}, {}});
Label* body_label = TopScope()->DeclarePrivateLabel(stmt->pos, "body");
Label* body_label = declarations()->DeclarePrivateLabel(stmt->pos, "body");
GenerateLabelDefinition(body_label);
Label* increment_label =
TopScope()->DeclarePrivateLabel(stmt->pos, "increment");
declarations()->DeclarePrivateLabel(stmt->pos, "increment");
GenerateLabelDefinition(increment_label);
Label* exit_label = TopScope()->DeclarePrivateLabel(stmt->pos, "exit");
Label* exit_label = declarations()->DeclarePrivateLabel(stmt->pos, "exit");
GenerateLabelDefinition(exit_label);
Type common_type = GetCommonType(stmt->pos, begin.type(), end.type());
@ -637,7 +654,8 @@ Type ImplementationVisitor::Visit(ForOfLoopStatement* stmt) {
VisitResult index_for_read = {index_var->type(),
index_var->GetValueForRead()};
Label* header_label = TopScope()->DeclarePrivateLabel(stmt->pos, "header");
Label* header_label =
declarations()->DeclarePrivateLabel(stmt->pos, "header");
GenerateLabelDefinition(header_label, stmt);
GenerateLabelGoto(header_label);
@ -676,7 +694,7 @@ Type ImplementationVisitor::Visit(ForOfLoopStatement* stmt) {
Type ImplementationVisitor::Visit(TryCatchStatement* stmt) {
ScopedIndent indent(this);
Label* try_done = TopScope()->DeclarePrivateLabel(stmt->pos, "try_done");
Label* try_done = declarations()->DeclarePrivateLabel(stmt->pos, "try_done");
GenerateLabelDefinition(try_done);
Type try_result = GetTypeOracle().GetNeverType();
std::vector<Label*> labels;
@ -684,16 +702,18 @@ Type ImplementationVisitor::Visit(TryCatchStatement* stmt) {
// Output labels for the goto handlers and for the merge after the try.
{
// Activate a new scope to see handler labels
Scope::Activator s(global_context_, stmt);
Declarations::NodeScopeActivator scope(declarations(), stmt);
for (LabelBlock* block : stmt->label_blocks) {
Label* label = Label::cast(LookupValue(block->pos, block->label));
Label* label =
Label::cast(declarations()->LookupValue(block->pos, block->label));
labels.push_back(label);
GenerateLabelDefinition(label);
}
size_t i = 0;
for (auto label : labels) {
Scope::Activator s(global_context_, stmt->label_blocks[i]->body);
Declarations::NodeScopeActivator scope(declarations(),
stmt->label_blocks[i]->body);
for (auto& v : label->GetParameters()) {
GenerateVariableDeclaration(stmt, v->name(), v->type());
v->Define();
@ -702,7 +722,7 @@ Type ImplementationVisitor::Visit(TryCatchStatement* stmt) {
}
Label* try_begin_label =
TopScope()->DeclarePrivateLabel(stmt->pos, "try_begin");
declarations()->DeclarePrivateLabel(stmt->pos, "try_begin");
GenerateLabelDefinition(try_begin_label);
GenerateLabelGoto(try_begin_label);
@ -717,17 +737,17 @@ Type ImplementationVisitor::Visit(TryCatchStatement* stmt) {
// Make sure that each label clause is actually used. It's not just a friendly
// thing to do, it will cause problems downstream in the compiler if there are
// bound labels that are never jumped to.
auto exception_iterator = stmt->label_blocks.begin();
auto label_iterator = stmt->label_blocks.begin();
for (auto label : labels) {
if (!label->IsUsed()) {
std::stringstream s;
s << "label ";
s << (*exception_iterator)->label;
s << (*label_iterator)->label;
s << " has a handler block but is never referred to in try block at "
<< PositionAsString((*exception_iterator)->pos);
<< PositionAsString((*label_iterator)->pos);
ReportError(s.str());
}
exception_iterator++;
label_iterator++;
}
// Visit and output the code for each catch block, one-by-one.
@ -763,27 +783,30 @@ Type ImplementationVisitor::Visit(ContinueStatement* stmt) {
}
Type ImplementationVisitor::Visit(ForLoopStatement* stmt) {
Scope::Activator s(global_context_, stmt);
Declarations::NodeScopeActivator scope(declarations(), stmt);
if (stmt->var_declaration) Visit(*stmt->var_declaration);
Label* body_label = nullptr;
Label* exit_label = nullptr;
{
Scope::Activator s(global_context_, stmt->test);
body_label = Label::cast(LookupValue(stmt->pos, kTrueLabelName));
Declarations::NodeScopeActivator scope(declarations(), stmt->test);
body_label =
Label::cast(declarations()->LookupValue(stmt->pos, kTrueLabelName));
GenerateLabelDefinition(body_label);
exit_label = Label::cast(LookupValue(stmt->pos, kFalseLabelName));
exit_label =
Label::cast(declarations()->LookupValue(stmt->pos, kFalseLabelName));
GenerateLabelDefinition(exit_label);
}
Label* header_label = TopScope()->DeclarePrivateLabel(stmt->pos, "header");
Label* header_label =
declarations()->DeclarePrivateLabel(stmt->pos, "header");
GenerateLabelDefinition(header_label, stmt);
GenerateLabelGoto(header_label);
GenerateLabelBind(header_label);
Label* assignment_label =
TopScope()->DeclarePrivateLabel(stmt->pos, "assignment");
declarations()->DeclarePrivateLabel(stmt->pos, "assignment");
GenerateLabelDefinition(assignment_label);
BreakContinueActivator activator(global_context_, exit_label,
@ -804,7 +827,7 @@ Type ImplementationVisitor::Visit(ForLoopStatement* stmt) {
Label* ImplementationVisitor::GetLabel(SourcePosition pos,
const std::string& label) {
Value* value = LookupValue(pos, label);
Value* value = declarations()->LookupValue(pos, label);
if (!value->IsLabel()) {
std::stringstream s;
s << label << " is not a label at " << PositionAsString(pos);
@ -874,7 +897,7 @@ void ImplementationVisitor::GenerateMacroFunctionDeclaration(
if (!first) {
o << ", ";
}
const Value* parameter = LookupValue(pos, name);
const Value* parameter = declarations()->LookupValue(pos, name);
Type parameter_type = *type_iterator;
const std::string& generated_type_name =
parameter_type.GetGeneratedTypeName();
@ -1050,10 +1073,10 @@ Variable* ImplementationVisitor::GenerateVariableDeclaration(
SourcePosition pos = node->pos;
Variable* variable = nullptr;
if (IsValueDeclared(name)) {
variable = Variable::cast(LookupValue(pos, name));
if (declarations()->Lookup(name)) {
variable = Variable::cast(declarations()->LookupValue(pos, name));
} else {
variable = TopScope()->DeclareVariable(pos, name, *type);
variable = declarations()->DeclareVariable(pos, name, *type);
// Because the variable is being defined during code generation, it must be
// assumed that it changes along all control split paths because it's no
// longer possible to run the control-flow anlaysis in the declaration pass
@ -1080,7 +1103,7 @@ Variable* ImplementationVisitor::GenerateVariableDeclaration(
void ImplementationVisitor::GenerateParameter(
SourcePosition pos, const std::string& parameter_name) {
const Value* val = LookupValue(pos, parameter_name);
const Value* val = declarations()->LookupValue(pos, parameter_name);
std::string var = val->GetValueForDeclaration();
GenerateIndent();
source_out() << val->type().GetGeneratedTypeName() << " " << var << " = ";
@ -1143,7 +1166,7 @@ VisitResult ImplementationVisitor::GenerateCall(
ReportError(stream.str());
}
source_out() << callable->name() << "(";
} else if (callable->IsRuntime()) {
} else if (callable->IsRuntimeFunction()) {
if (is_tailcall) {
source_out() << "TailCallRuntime(Runtime::k" << callable->name() << ", ";
} else {
@ -1272,7 +1295,7 @@ bool ImplementationVisitor::GenerateExpressionBranch(
Expression* expression, const std::vector<Label*>& statement_labels,
const std::vector<Statement*>& statement_blocks, Label* merge_label) {
// Activate a new scope to define True/False catch labels
Scope::Activator s(global_context_, expression);
Declarations::NodeScopeActivator scope(declarations(), expression);
VisitResult expression_result = Visit(expression);
if (expression_result.type() == GetTypeOracle().GetBitType()) {

View File

@ -30,7 +30,7 @@ class ImplementationVisitor : public FileVisitor {
explicit ImplementationVisitor(GlobalContext& global_context)
: FileVisitor(global_context), indent_(0), next_temp_(0) {}
void Visit(Ast* ast) { Visit(ast->GetDefaultModule()); }
void Visit(Ast* ast) { Visit(ast->default_module()); }
VisitResult Visit(Expression* expr);
Type Visit(Statement* stmt);
@ -38,7 +38,8 @@ class ImplementationVisitor : public FileVisitor {
LocationReference GetLocationReference(LocationExpression* location);
LocationReference GetLocationReference(IdentifierExpression* expr) {
return LocationReference(LookupValue(expr->pos, expr->name), {}, {});
return LocationReference(declarations()->LookupValue(expr->pos, expr->name),
{}, {});
}
LocationReference GetLocationReference(FieldAccessExpression* expr) {
return LocationReference({}, Visit(expr->object), {});

View File

@ -14,147 +14,37 @@ namespace v8 {
namespace internal {
namespace torque {
Scope::Scope(GlobalContext& global_context)
: global_context_(global_context),
scope_number_(global_context.GetNextScopeNumber()),
private_label_number_(0) {
global_context.RegisterScope(this);
}
Scope::Scope(ScopeChain& scope_chain)
: scope_chain_(scope_chain),
scope_number_(scope_chain_.GetNextScopeNumber()),
private_label_number_(0) {}
Macro* Scope::DeclareMacro(SourcePosition pos, const std::string& name,
Scope* scope, const Signature& signature) {
auto i = lookup_.find(name);
if (i == lookup_.end()) {
lookup_[name] = std::unique_ptr<MacroList>(new MacroList());
i = lookup_.find(name);
} else if (i->second->kind() != Declarable::kMacroList) {
std::stringstream s;
s << "cannot redeclare " << name << " as a non-macro at "
<< global_context_.PositionAsString(pos);
ReportError(s.str());
}
MacroList* macro_list = MacroList::cast(i->second.get());
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 << global_context_.PositionAsString(pos);
ReportError(s.str());
}
}
Macro* result = macro_list->AddMacro(
std::unique_ptr<Macro>(new Macro(name, scope, signature)));
if (global_context_.verbose()) {
std::cout << "declared " << *result << "\n";
}
return result;
}
Builtin* Scope::DeclareBuiltin(SourcePosition pos, const std::string& name,
Builtin::Kind kind, Scope* scope,
const Signature& signature) {
CheckAlreadyDeclared(pos, name, "builtin");
Builtin* result = new Builtin(name, kind, scope, signature);
lookup_[name] = std::unique_ptr<Builtin>(result);
if (global_context_.verbose()) {
std::cout << "declared " << *result << "\n";
}
return result;
}
Runtime* Scope::DeclareRuntime(SourcePosition pos, const std::string& name,
Scope* scope, const Signature& signature) {
CheckAlreadyDeclared(pos, name, "runtime");
Runtime* result = new Runtime(name, scope, signature);
lookup_[name] = std::unique_ptr<Runtime>(result);
if (global_context_.verbose()) {
std::cout << "declared " << *result << "\n";
}
return result;
}
Variable* Scope::DeclareVariable(SourcePosition pos, const std::string& var,
Type type) {
std::string name(std::string("v") + "_" + var +
std::to_string(scope_number_));
CheckAlreadyDeclared(pos, var, "variable");
Variable* result = new Variable(var, name, type);
lookup_[var] = std::unique_ptr<Variable>(result);
if (global_context_.verbose()) {
std::cout << "declared " << var << " (type " << type << ")\n";
}
return result;
}
Parameter* Scope::DeclareParameter(SourcePosition pos, const std::string& name,
const std::string& var_name, Type type) {
CheckAlreadyDeclared(pos, name, "parameter");
Parameter* result = new Parameter(name, type, var_name);
lookup_[name] = std::unique_ptr<Parameter>(result);
return result;
}
Label* Scope::DeclareLabel(SourcePosition pos, const std::string& name) {
CheckAlreadyDeclared(pos, name, "label");
Label* result = new Label(name);
lookup_[name] = std::unique_ptr<Label>(result);
return result;
}
Label* Scope::DeclarePrivateLabel(SourcePosition pos,
const std::string& raw_name) {
std::string name = raw_name + "_" + std::to_string(private_label_number_++);
CheckAlreadyDeclared(pos, name, "label");
Label* result = new Label(name);
lookup_[name] = std::unique_ptr<Label>(result);
return result;
}
void Scope::DeclareConstant(SourcePosition pos, const std::string& name,
Type type, const std::string& value) {
CheckAlreadyDeclared(pos, name, "constant, parameter or arguments");
lookup_[name] = std::unique_ptr<Constant>(new Constant(name, type, value));
Scope* ScopeChain::NewScope() {
Scope* new_scope = new Scope(*this);
scopes_.emplace_back(std::unique_ptr<Scope>(new_scope));
return new_scope;
}
void Scope::AddLiveVariables(std::set<const Variable*>& set) {
for (auto& current : lookup_) {
if (current.second->IsVariable()) {
set.insert(Variable::cast(current.second.get()));
set.insert(Variable::cast(current.second));
}
}
}
void Scope::CheckAlreadyDeclared(SourcePosition pos, const std::string& name,
const char* new_type) {
auto i = lookup_.find(name);
if (i != lookup_.end()) {
std::stringstream s;
s << "cannot redeclare " << name << " (type " << new_type << ") at "
<< global_context_.PositionAsString(pos)
<< " (it's already declared as a " << i->second->type_name() << ")\n";
ReportError(s.str());
}
}
void Scope::Print() {
std::cout << "scope #" << std::to_string(scope_number_) << "\n";
for (auto& i : lookup_) {
std::cout << i.first << ": " << i.second.get() << "\n";
std::cout << i.first << ": " << i.second << "\n";
}
}
Scope::Activator::Activator(Scope* scope) : scope_(scope) {
scope->global_context().PushScope(scope);
scope->GetScopeChain().PushScope(scope);
}
Scope::Activator::Activator(GlobalContext& global_context, const AstNode* node)
: Activator(global_context.GetParserRuleContextScope(node)) {}
Scope::Activator::~Activator() { scope_->global_context().PopScope(); }
Scope::Activator::~Activator() { scope_->GetScopeChain().PopScope(); }
} // namespace torque
} // namespace internal

View File

@ -16,49 +16,11 @@ namespace v8 {
namespace internal {
namespace torque {
class Builtin;
class Callable;
class Declarable;
class GlobalContext;
class Macro;
class Parameter;
class Runtime;
class Variable;
class ScopeChain;
class Scope {
public:
explicit Scope(GlobalContext& global_context);
Macro* DeclareMacro(SourcePosition pos, const std::string& name, Scope* scope,
const Signature& signature);
Builtin* DeclareBuiltin(SourcePosition pos, const std::string& name,
Builtin::Kind kind, Scope* scope,
const Signature& signature);
Runtime* DeclareRuntime(SourcePosition pos, const std::string& name,
Scope* scope, const Signature& signature);
Variable* DeclareVariable(SourcePosition pos, const std::string& var,
Type type);
Parameter* DeclareParameter(SourcePosition pos, const std::string& name,
const std::string& mangled_name, Type type);
Label* DeclareLabel(SourcePosition pos, const std::string& name);
Label* DeclarePrivateLabel(SourcePosition pos, const std::string& name);
void DeclareConstant(SourcePosition pos, const std::string& name, Type type,
const std::string& value);
Declarable* Lookup(const std::string& name) {
auto i = lookup_.find(name);
if (i == lookup_.end()) {
return nullptr;
}
return i->second.get();
}
explicit Scope(ScopeChain& scope_chain);
void Stream(std::ostream& stream) const {
stream << "scope " << std::to_string(scope_number_) << " {";
@ -68,7 +30,9 @@ class Scope {
stream << "}";
}
GlobalContext& global_context() const { return global_context_; }
int scope_number() const { return scope_number_; }
ScopeChain& GetScopeChain() const { return scope_chain_; }
void AddLiveVariables(std::set<const Variable*>& set);
@ -77,18 +41,33 @@ class Scope {
class Activator;
private:
friend class ScopeChain;
void CheckAlreadyDeclared(SourcePosition pos, const std::string& name,
const char* new_type);
GlobalContext& global_context_;
void Declare(const std::string& name, Declarable* d) {
DCHECK_EQ(lookup_.end(), lookup_.find(name));
DCHECK(d != nullptr);
lookup_[name] = d;
}
Declarable* Lookup(const std::string& name) {
auto i = lookup_.find(name);
if (i == lookup_.end()) {
return nullptr;
}
return i->second;
}
ScopeChain& scope_chain_;
int scope_number_;
int private_label_number_;
std::map<std::string, std::unique_ptr<Declarable>> lookup_;
std::map<std::string, Declarable*> lookup_;
};
class Scope::Activator {
public:
explicit Activator(GlobalContext& global_context, const AstNode* node);
explicit Activator(Scope* scope);
~Activator();
@ -96,6 +75,59 @@ class Scope::Activator {
Scope* scope_;
};
class ScopeChain {
public:
ScopeChain() : next_scope_number_(0) {}
Scope* NewScope();
Scope* TopScope() const { return current_scopes_.back(); }
void PushScope(Scope* scope) { current_scopes_.push_back(scope); }
void PopScope() { current_scopes_.pop_back(); }
std::set<const Variable*> GetLiveVariables() {
std::set<const Variable*> result;
for (auto scope : current_scopes_) {
scope->AddLiveVariables(result);
}
return result;
}
void Declare(const std::string& name, Declarable* d) {
TopScope()->Declare(name, d);
}
Declarable* Lookup(const std::string& name) {
auto e = current_scopes_.rend();
auto c = current_scopes_.rbegin();
while (c != e) {
Declarable* result = (*c)->Lookup(name);
if (result != nullptr) return result;
++c;
}
return nullptr;
}
Declarable* ShallowLookup(const std::string& name) {
auto& e = current_scopes_.back();
return e->Lookup(name);
}
void Print() {
for (auto s : current_scopes_) {
s->Print();
}
}
private:
friend class Scope;
int GetNextScopeNumber() { return next_scope_number_++; }
int next_scope_number_;
std::vector<std::unique_ptr<Scope>> scopes_;
std::vector<Scope*> current_scopes_;
};
inline std::ostream& operator<<(std::ostream& os, const Scope& scope) {
scope.Stream(os);
return os;

View File

@ -86,6 +86,7 @@ int WrappedMain(int argc, const char** argv) {
if (output_directory.length() != 0) {
{
DeclarationVisitor visitor(global_context);
visitor.Visit(global_context.ast());
std::string output_header_path = output_directory;

View File

@ -5,6 +5,8 @@
#ifndef V8_TORQUE_TYPE_ORACLE_H_
#define V8_TORQUE_TYPE_ORACLE_H_
#include "src/torque/declarable.h"
#include "src/torque/declarations.h"
#include "src/torque/types.h"
#include "src/torque/utils.h"
@ -14,62 +16,28 @@ namespace torque {
class TypeOracle {
public:
void RegisterTypeImpl(const std::string& name, const std::string& generated,
const std::string* parent = nullptr) {
TypeImpl* parent_class = nullptr;
if (type_impls_.find(name) != type_impls_.end()) {
ReportError(std::string("cannot redefine type class ") + name);
}
if (parent != nullptr) {
auto i = type_impls_.find(*parent);
if (i == type_impls_.end()) {
std::stringstream s;
s << "cannot find parent type class " << *parent << " for " << name;
ReportError(s.str());
}
parent_class = i->second.get();
}
TypeImpl* new_class = new TypeImpl(parent_class, name, generated);
type_impls_[name] = std::unique_ptr<TypeImpl>(new_class);
}
explicit TypeOracle(Declarations* declarations)
: declarations_(declarations) {}
void RegisterImplicitConversion(Type to, Type from) {
implicit_conversions_.push_back(std::make_pair(to, from));
}
Type GetType(const std::string& type_name) {
auto i = type_impls_.find(type_name);
if (i == type_impls_.end()) {
std::stringstream s;
s << "no type class found for type " << type_name;
ReportError(s.str());
}
return Type(i->second.get());
}
Type GetArgumentsType() { return GetBuiltinType(ARGUMENTS_TYPE_STRING); }
Type GetArgumentsType() { return GetType(ARGUMENTS_TYPE_STRING); }
Type GetBitType() { return GetBuiltinType(BIT_TYPE_STRING); }
Type GetTaggedType() { return GetType(TAGGED_TYPE_STRING); }
Type GetVoidType() { return GetBuiltinType(VOID_TYPE_STRING); }
Type GetExceptionType() { return GetType(EXCEPTION_TYPE_STRING); }
Type GetObjectType() { return GetBuiltinType(OBJECT_TYPE_STRING); }
Type GetBranchType() { return GetType(BRANCH_TYPE_STRING); }
Type GetStringType() { return GetBuiltinType(STRING_TYPE_STRING); }
Type GetBitType() { return GetType(BIT_TYPE_STRING); }
Type GetIntPtrType() { return GetBuiltinType(INTPTR_TYPE_STRING); }
Type GetVoidType() { return GetType(VOID_TYPE_STRING); }
Type GetNeverType() { return GetBuiltinType(NEVER_TYPE_STRING); }
Type GetObjectType() { return GetType(OBJECT_TYPE_STRING); }
Type GetStringType() { return GetType(STRING_TYPE_STRING); }
Type GetIntPtrType() { return GetType(INTPTR_TYPE_STRING); }
Type GetNeverType() { return GetType(NEVER_TYPE_STRING); }
Type GetConstInt31Type() { return GetType(CONST_INT31_TYPE_STRING); }
bool IsException(Type from) { return GetExceptionType().IsSubclass(from); }
Type GetConstInt31Type() { return GetBuiltinType(CONST_INT31_TYPE_STRING); }
bool IsAssignableFrom(Type to, Type from) {
if (to.IsSubclass(from)) return true;
@ -99,7 +67,13 @@ class TypeOracle {
}
private:
std::map<std::string, std::unique_ptr<TypeImpl>> type_impls_;
Type GetBuiltinType(const std::string& name) {
Declarable* declarable = declarations_->Lookup(name);
DCHECK(declarable != nullptr);
return Type(TypeImpl::cast(declarable));
}
Declarations* declarations_;
std::vector<std::pair<Type, Type>> implicit_conversions_;
};

View File

@ -5,12 +5,38 @@
#include <fstream>
#include <iostream>
#include "src/torque/declarable.h"
#include "src/torque/types.h"
namespace v8 {
namespace internal {
namespace torque {
bool Type::Is(const std::string& name) const { return name == impl_->name(); }
const std::string& Type::name() const { return impl_->name(); }
bool Type::IsSubclass(Type from) {
TypeImpl* to_class = type_impl();
TypeImpl* from_class = from.type_impl();
while (from_class != nullptr) {
if (to_class == from_class) return true;
from_class = from_class->parent();
}
return false;
}
const std::string& Type::GetGeneratedTypeName() const {
return type_impl()->generated_type();
}
std::string Type::GetGeneratedTNodeTypeName() const {
std::string result = type_impl()->generated_type();
DCHECK_EQ(result.substr(0, 6), "TNode<");
result = result.substr(6, result.length() - 7);
return result;
}
std::ostream& operator<<(std::ostream& os, const Signature& sig) {
os << "(";
for (size_t i = 0; i < sig.parameter_names.size(); ++i) {

View File

@ -31,21 +31,7 @@ static const char* const CONST_FLOAT64_TYPE_STRING = "const_float64";
class Label;
struct Type;
class TypeImpl {
public:
TypeImpl(TypeImpl* parent, const std::string& name,
const std::string& generated_type)
: parent_(parent), name_(name), generated_type_(generated_type) {}
TypeImpl* parent() const { return parent_; }
const std::string& name() const { return name_; }
const std::string& generated_type() const { return generated_type_; }
private:
TypeImpl* parent_;
std::string name_;
std::string generated_type_;
};
class TypeImpl;
typedef struct Type {
public:
@ -54,17 +40,9 @@ typedef struct Type {
bool operator==(const Type& other) const { return impl_ == other.impl_; }
bool operator!=(const Type& other) const { return impl_ != other.impl_; }
bool Is(const Type& other) const { return impl_ == other.impl_; }
bool Is(const std::string& name) const { return name == impl_->name(); }
bool Is(const std::string& name) const;
bool IsSubclass(Type from) {
TypeImpl* to_class = type_impl();
TypeImpl* from_class = from.type_impl();
while (from_class != nullptr) {
if (to_class == from_class) return true;
from_class = from_class->parent();
}
return false;
}
bool IsSubclass(Type from);
bool IsException() const { return name() == EXCEPTION_TYPE_STRING; }
bool IsVoid() const { return name() == VOID_TYPE_STRING; }
@ -72,17 +50,11 @@ typedef struct Type {
bool IsBit() const { return name() == BIT_TYPE_STRING; }
bool IsVoidOrNever() const { return IsVoid() || IsNever(); }
const std::string& name() const { return impl_->name(); }
const std::string& name() const;
const std::string& GetGeneratedTypeName() const {
return type_impl()->generated_type();
}
const std::string& GetGeneratedTypeName() const;
std::string GetGeneratedTNodeTypeName() const {
std::string result = type_impl()->generated_type();
result = result.substr(6, result.length() - 7);
return result;
}
std::string GetGeneratedTNodeTypeName() const;
protected:
TypeImpl* type_impl() const { return impl_; }