Commit 185eaec0 authored by Tobias Tebbi's avatar Tobias Tebbi Committed by Commit Bot

[torque] declare local value and label bindings in the ImplementationVisitor

While this is mostly a mechanical change to enable re-visiting macros for
inlining, it has a few user-facing effects:

- Labels and (variables, parameters, local constants) are handled separately,
  so they do not shadow each other.
- A local variable or constant is not bound in its initializer.
  This allows code like:

  const x = 5;
  {
    const x = x + 1;
  }


Bug: v8:7793
Change-Id: I968e1f93d92689737362c803342a797d312e95cd
Reviewed-on: https://chromium-review.googlesource.com/c/1276628
Commit-Queue: Tobias Tebbi <tebbi@chromium.org>
Reviewed-by: 's avatarDaniel Clifford <danno@chromium.org>
Cr-Commit-Position: refs/heads/master@{#56649}
parent fa3b5d7e
......@@ -53,7 +53,7 @@ namespace torque {
V(AssertStatement) \
V(TailCallStatement) \
V(VarDeclarationStatement) \
V(GotoStatement) \
V(GotoStatement)
#define AST_DECLARATION_NODE_KIND_LIST(V) \
V(TypeDeclaration) \
......@@ -510,7 +510,7 @@ struct ForLoopStatement : Statement {
DEFINE_AST_NODE_LEAF_BOILERPLATE(ForLoopStatement)
ForLoopStatement(SourcePosition pos, base::Optional<Statement*> declaration,
base::Optional<Expression*> test,
base::Optional<Expression*> action, Statement* body)
base::Optional<Statement*> action, Statement* body)
: Statement(kKind, pos),
var_declaration(),
test(std::move(test)),
......@@ -521,7 +521,7 @@ struct ForLoopStatement : Statement {
}
base::Optional<VarDeclarationStatement*> var_declaration;
base::Optional<Expression*> test;
base::Optional<Expression*> action;
base::Optional<Statement*> action;
Statement* body;
};
......@@ -815,6 +815,13 @@ bool AstNodeClassCheck::IsInstanceOf(AstNode* node) {
#undef ENUM_ITEM
inline bool IsDeferred(Statement* stmt) {
if (auto* block = BlockStatement::DynamicCast(stmt)) {
return block->deferred;
}
return false;
}
} // namespace torque
} // namespace internal
} // namespace v8
......
......@@ -32,11 +32,6 @@ std::ostream& operator<<(std::ostream& os, const Callable& m) {
return os;
}
std::ostream& operator<<(std::ostream& os, const Variable& v) {
os << "variable " << v.name() << ": " << *v.type();
return os;
}
std::ostream& operator<<(std::ostream& os, const Builtin& b) {
os << "builtin " << *b.signature().return_type << " " << b.name()
<< b.signature().parameter_types;
......@@ -49,33 +44,6 @@ std::ostream& operator<<(std::ostream& os, const RuntimeFunction& b) {
return os;
}
void PrintLabel(std::ostream& os, const Label& l, bool with_names) {
os << l.name();
if (l.GetParameterCount() != 0) {
os << "(";
if (with_names) {
PrintCommaSeparatedList(os, l.GetParameters(),
[](Variable* v) -> std::string {
std::stringstream stream;
stream << v->name();
stream << ": ";
stream << *(v->type());
return stream.str();
});
} else {
PrintCommaSeparatedList(
os, l.GetParameters(),
[](Variable* v) -> const Type& { return *(v->type()); });
}
os << ")";
}
}
std::ostream& operator<<(std::ostream& os, const Label& l) {
PrintLabel(os, l, true);
return os;
}
std::ostream& operator<<(std::ostream& os, const Generic& g) {
os << "generic " << g.name() << "<";
PrintCommaSeparatedList(os, g.declaration()->generic_parameters);
......@@ -84,8 +52,6 @@ std::ostream& operator<<(std::ostream& os, const Generic& g) {
return os;
}
size_t Label::next_id_ = 0;
} // namespace torque
} // namespace internal
} // namespace v8
......@@ -27,8 +27,6 @@ class Declarable {
public:
virtual ~Declarable() = default;
enum Kind {
kVariable,
kParameter,
kMacro,
kMacroList,
kBuiltin,
......@@ -36,7 +34,6 @@ class Declarable {
kGeneric,
kGenericList,
kTypeAlias,
kLabel,
kExternConstant,
kModuleConstant
};
......@@ -46,17 +43,11 @@ class Declarable {
bool IsRuntimeFunction() const { return kind() == kRuntimeFunction; }
bool IsGeneric() const { return kind() == kGeneric; }
bool IsTypeAlias() const { return kind() == kTypeAlias; }
bool IsParameter() const { return kind() == kParameter; }
bool IsLabel() const { return kind() == kLabel; }
bool IsVariable() const { return kind() == kVariable; }
bool IsMacroList() const { return kind() == kMacroList; }
bool IsGenericList() const { return kind() == kGenericList; }
bool IsExternConstant() const { return kind() == kExternConstant; }
bool IsModuleConstant() const { return kind() == kModuleConstant; }
bool IsValue() const {
return IsVariable() || IsExternConstant() || IsParameter() ||
IsModuleConstant();
}
bool IsValue() const { return IsExternConstant() || IsModuleConstant(); }
virtual const char* type_name() const { return "<<unknown>>"; }
protected:
......@@ -110,22 +101,6 @@ class Value : public Declarable {
base::Optional<VisitResult> value_;
};
class Parameter : public Value {
public:
DECLARE_DECLARABLE_BOILERPLATE(Parameter, parameter);
const std::string& external_name() const { return external_name_; }
private:
friend class Declarations;
Parameter(const std::string& name, std::string external_name,
const Type* type)
: Value(Declarable::kParameter, type, name),
external_name_(external_name) {}
std::string external_name_;
};
class ModuleConstant : public Value {
public:
DECLARE_DECLARABLE_BOILERPLATE(ModuleConstant, constant);
......@@ -141,75 +116,6 @@ class ModuleConstant : public Value {
std::string constant_name_;
};
class Variable : public Value {
public:
DECLARE_DECLARABLE_BOILERPLATE(Variable, variable);
bool IsConst() const override { return const_; }
void Define() {
if (defined_ && IsConst()) {
ReportError("Cannot re-define a const-bound variable.");
}
defined_ = true;
}
bool IsDefined() const { return defined_; }
private:
friend class Declarations;
Variable(std::string name, const Type* type, bool is_const)
: Value(Declarable::kVariable, type, name),
defined_(false),
const_(is_const) {
DCHECK_IMPLIES(type->IsConstexpr(), IsConst());
}
std::string value_;
bool defined_;
bool const_;
};
class Label : public Declarable {
public:
void AddVariable(Variable* var) { parameters_.push_back(var); }
Block* block() const { return *block_; }
void set_block(Block* block) {
DCHECK(!block_);
block_ = block;
}
const std::string& external_label_name() const {
return *external_label_name_;
}
const std::string& name() const { return name_; }
void set_external_label_name(std::string external_label_name) {
DCHECK(!block_);
DCHECK(!external_label_name_);
external_label_name_ = std::move(external_label_name);
}
Variable* GetParameter(size_t i) const { return parameters_[i]; }
size_t GetParameterCount() const { return parameters_.size(); }
const std::vector<Variable*>& GetParameters() const { return parameters_; }
DECLARE_DECLARABLE_BOILERPLATE(Label, label);
void MarkUsed() { used_ = true; }
bool IsUsed() const { return used_; }
bool IsDeferred() const { return deferred_; }
private:
friend class Declarations;
explicit Label(std::string name, bool deferred = false)
: Declarable(Declarable::kLabel),
name_(std::move(name)),
used_(false),
deferred_(deferred) {}
std::string name_;
base::Optional<Block*> block_;
base::Optional<std::string> external_label_name_;
std::vector<Variable*> parameters_;
static size_t next_id_;
bool used_;
bool deferred_;
};
class ExternConstant : public Value {
public:
DECLARE_DECLARABLE_BOILERPLATE(ExternConstant, constant);
......@@ -380,12 +286,8 @@ class TypeAlias : public Declarable {
const Type* type_;
};
void PrintLabel(std::ostream& os, const Label& l, bool with_names);
std::ostream& operator<<(std::ostream& os, const Callable& m);
std::ostream& operator<<(std::ostream& os, const Variable& v);
std::ostream& operator<<(std::ostream& os, const Builtin& b);
std::ostream& operator<<(std::ostream& os, const Label& l);
std::ostream& operator<<(std::ostream& os, const RuntimeFunction& b);
std::ostream& operator<<(std::ostream& os, const Generic& g);
......
......@@ -154,12 +154,6 @@ void DeclarationVisitor::Visit(TorqueBuiltinDeclaration* decl,
const Signature& signature, Statement* body) {
Builtin* builtin = BuiltinDeclarationCommon(decl, false, signature);
CurrentCallableActivator activator(global_context_, builtin, decl);
DeclareSignature(signature);
if (signature.parameter_types.var_args) {
declarations()->DeclareExternConstant(
decl->signature->parameters.arguments_variable,
TypeOracle::GetArgumentsType(), "arguments");
}
torque_builtins_.push_back(builtin);
Visit(body);
}
......@@ -173,8 +167,6 @@ void DeclarationVisitor::Visit(TorqueMacroDeclaration* decl,
CurrentCallableActivator activator(global_context_, macro, decl);
DeclareSignature(signature);
if (body != nullptr) {
Visit(body);
}
......@@ -259,51 +251,10 @@ void DeclarationVisitor::Visit(ReturnStatement* stmt) {
}
}
Variable* DeclarationVisitor::DeclareVariable(const std::string& name,
const Type* type, bool is_const) {
Variable* result = declarations()->DeclareVariable(name, type, is_const);
return result;
}
Parameter* DeclarationVisitor::DeclareParameter(const std::string& name,
const Type* type) {
return declarations()->DeclareParameter(
name, GetParameterVariableFromName(name), type);
}
void DeclarationVisitor::Visit(VarDeclarationStatement* stmt) {
std::string variable_name = stmt->name;
if (!stmt->const_qualified) {
if (!stmt->type) {
ReportError(
"variable declaration is missing type. Only 'const' bindings can "
"infer the type.");
}
const Type* type = declarations()->GetType(*stmt->type);
if (type->IsConstexpr()) {
ReportError(
"cannot declare variable with constexpr type. Use 'const' instead.");
}
DeclareVariable(variable_name, type, stmt->const_qualified);
if (global_context_.verbose()) {
std::cout << "declared variable " << variable_name << " with type "
<< *type << "\n";
}
}
// const qualified variables are required to be initialized properly.
if (stmt->const_qualified && !stmt->initializer) {
std::stringstream stream;
stream << "local constant \"" << variable_name << "\" is not initialized.";
ReportError(stream.str());
}
if (stmt->initializer) {
Visit(*stmt->initializer);
if (global_context_.verbose()) {
std::cout << "variable has initialization expression at "
<< CurrentPositionAsString() << "\n";
}
}
}
......@@ -329,53 +280,29 @@ void DeclarationVisitor::Visit(StructDeclaration* decl) {
}
void DeclarationVisitor::Visit(LogicalOrExpression* expr) {
{
Declarations::NodeScopeActivator scope(declarations(), expr->left);
declarations()->DeclareLabel(kFalseLabelName);
Visit(expr->left);
}
Visit(expr->right);
}
void DeclarationVisitor::Visit(LogicalAndExpression* expr) {
{
Declarations::NodeScopeActivator scope(declarations(), expr->left);
declarations()->DeclareLabel(kTrueLabelName);
Visit(expr->left);
}
Visit(expr->right);
}
void DeclarationVisitor::DeclareExpressionForBranch(
Expression* node, base::Optional<Statement*> true_statement,
base::Optional<Statement*> false_statement) {
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.
declarations()->DeclareLabel(kTrueLabelName, true_statement);
declarations()->DeclareLabel(kFalseLabelName, false_statement);
Visit(node);
}
void DeclarationVisitor::Visit(ConditionalExpression* expr) {
DeclareExpressionForBranch(expr->condition);
Visit(expr->condition);
Visit(expr->if_true);
Visit(expr->if_false);
}
void DeclarationVisitor::Visit(IfStatement* stmt) {
DeclareExpressionForBranch(stmt->condition, stmt->if_true, stmt->if_false);
Visit(stmt->condition);
Visit(stmt->if_true);
if (stmt->if_false) Visit(*stmt->if_false);
}
void DeclarationVisitor::Visit(WhileStatement* stmt) {
Declarations::NodeScopeActivator scope(declarations(), stmt);
DeclareExpressionForBranch(stmt->condition);
Visit(stmt->condition);
Visit(stmt->body);
}
......@@ -390,59 +317,14 @@ void DeclarationVisitor::Visit(ForOfLoopStatement* stmt) {
}
void DeclarationVisitor::Visit(ForLoopStatement* stmt) {
Declarations::NodeScopeActivator scope(declarations(), stmt);
if (stmt->var_declaration) Visit(*stmt->var_declaration);
// Same as DeclareExpressionForBranch, but without the extra scope.
// If no test expression is present we can not use it for the scope.
declarations()->DeclareLabel(kTrueLabelName);
declarations()->DeclareLabel(kFalseLabelName);
if (stmt->test) Visit(*stmt->test);
Visit(stmt->body);
if (stmt->action) Visit(*stmt->action);
}
void DeclarationVisitor::Visit(TryLabelExpression* stmt) {
// Activate a new scope to declare the handler's label parameters, they should
// not be visible outside the label block.
{
Declarations::NodeScopeActivator scope(declarations(), stmt);
// Declare label
{
LabelBlock* block = stmt->label_block;
CurrentSourcePosition::Scope scope(block->pos);
Label* shared_label =
declarations()->DeclareLabel(block->label, block->body);
{
Declarations::NodeScopeActivator scope(declarations(), block->body);
if (block->parameters.has_varargs) {
std::stringstream stream;
stream << "cannot use ... for label parameters";
ReportError(stream.str());
}
size_t i = 0;
for (const auto& p : block->parameters.names) {
const Type* type =
declarations()->GetType(block->parameters.types[i]);
if (type->IsConstexpr()) {
ReportError("no constexpr type allowed for label arguments");
}
shared_label->AddVariable(DeclareVariable(p, type, false));
++i;
}
if (global_context_.verbose()) {
std::cout << " declaring label " << block->label << "\n";
}
}
}
Visit(stmt->try_expression);
}
Visit(stmt->try_expression);
Visit(stmt->label_block->body);
}
......@@ -540,31 +422,6 @@ void DeclarationVisitor::Visit(TypeDeclaration* decl) {
}
}
void DeclarationVisitor::DeclareSignature(const Signature& signature) {
auto type_iterator = signature.parameter_types.types.begin();
for (const auto& name : signature.parameter_names) {
const Type* t(*type_iterator++);
if (name.size() != 0) {
DeclareParameter(name, t);
}
}
for (auto& label : signature.labels) {
auto label_params = label.types;
Label* new_label = declarations()->DeclareLabel(label.name);
new_label->set_external_label_name("label_" + label.name);
size_t i = 0;
for (auto var_type : label_params) {
if (var_type->IsConstexpr()) {
ReportError("no constexpr type allowed for label arguments");
}
std::string var_name = label.name + std::to_string(i++);
new_label->AddVariable(
declarations()->CreateVariable(var_name, var_type, false));
}
}
}
void DeclarationVisitor::DeclareSpecializedTypes(const SpecializationKey& key) {
size_t i = 0;
Generic* generic = key.first;
......
......@@ -103,7 +103,7 @@ class DeclarationVisitor : public FileVisitor {
#if defined(DEBUG)
do_check = true;
#endif
if (do_check) DeclareExpressionForBranch(stmt->expression);
if (do_check) Visit(stmt->expression);
}
void Visit(VarDeclarationStatement* stmt);
......@@ -114,10 +114,6 @@ class DeclarationVisitor : public FileVisitor {
void Visit(LogicalOrExpression* expr);
void Visit(LogicalAndExpression* expr);
void DeclareExpressionForBranch(
Expression* node, base::Optional<Statement*> true_statement = {},
base::Optional<Statement*> false_statement = {});
void Visit(ConditionalExpression* expr);
void Visit(IfStatement* stmt);
void Visit(WhileStatement* stmt);
......@@ -144,11 +140,6 @@ class DeclarationVisitor : public FileVisitor {
void GenerateHeader(std::string& file_name);
private:
Variable* DeclareVariable(const std::string& name, const Type* type,
bool is_const);
Parameter* DeclareParameter(const std::string& name, const Type* type);
void DeclareSignature(const Signature& signature);
void DeclareSpecializedTypes(const SpecializationKey& key);
void Specialize(const SpecializationKey& key, CallableNode* callable,
......
......@@ -121,16 +121,6 @@ Value* Declarations::LookupValue(const std::string& name) {
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);
......@@ -234,19 +224,6 @@ void Declarations::DeclareStruct(Module* module, const std::string& name,
DeclareType(name, new_type);
}
Label* Declarations::DeclareLabel(const std::string& name,
base::Optional<Statement*> statement) {
CheckAlreadyDeclared(name, "label");
bool deferred = false;
if (statement) {
BlockStatement* block = BlockStatement::DynamicCast(*statement);
deferred = block && block->deferred;
}
Label* result = new Label(name, deferred);
Declare(name, std::unique_ptr<Declarable>(result));
return result;
}
MacroList* Declarations::GetMacroListForName(const std::string& name,
const Signature& signature) {
auto previous = chain_.Lookup(name);
......@@ -305,29 +282,6 @@ RuntimeFunction* Declarations::DeclareRuntimeFunction(
return result;
}
Variable* Declarations::CreateVariable(const std::string& var, const Type* type,
bool is_const) {
return RegisterDeclarable(
std::unique_ptr<Variable>(new Variable(var, type, is_const)));
}
Variable* Declarations::DeclareVariable(const std::string& var,
const Type* type, bool is_const) {
CheckAlreadyDeclared(var, "variable");
Variable* result = new Variable(var, type, is_const);
Declare(var, std::unique_ptr<Declarable>(result));
return result;
}
Parameter* Declarations::DeclareParameter(const std::string& name,
std::string external_name,
const Type* type) {
CheckAlreadyDeclared(name, "parameter");
Parameter* result = new Parameter(name, std::move(external_name), type);
Declare(name, std::unique_ptr<Declarable>(result));
return result;
}
void Declarations::DeclareExternConstant(const std::string& name,
const Type* type, std::string value) {
CheckAlreadyDeclared(name, "constant, parameter or arguments");
......
......@@ -60,12 +60,6 @@ class Declarations {
Builtin* LookupBuiltin(const std::string& name);
Label* TryLookupLabel(const std::string& name) {
Declarable* d = TryLookup(name);
return d && d->IsLabel() ? Label::cast(d) : nullptr;
}
Label* LookupLabel(const std::string& name);
GenericList* LookupGeneric(const std::string& name);
ModuleConstant* LookupModuleConstant(const std::string& name);
......@@ -79,9 +73,6 @@ class Declarations {
void DeclareStruct(Module* module, const std::string& name,
const std::vector<NameAndType>& fields);
Label* DeclareLabel(const std::string& name,
base::Optional<Statement*> statement = {});
Macro* DeclareMacro(const std::string& name, const Signature& signature,
base::Optional<std::string> op = {});
......@@ -91,14 +82,6 @@ class Declarations {
RuntimeFunction* DeclareRuntimeFunction(const std::string& name,
const Signature& signature);
Variable* CreateVariable(const std::string& var, const Type* type,
bool is_const);
Variable* DeclareVariable(const std::string& var, const Type* type,
bool is_const);
Parameter* DeclareParameter(const std::string& name,
std::string external_name, const Type* type);
void DeclareExternConstant(const std::string& name, const Type* type,
std::string value);
ModuleConstant* DeclareModuleConstant(const std::string& name,
......@@ -112,10 +95,6 @@ class Declarations {
ScopeChain::Snapshot GetScopeChainSnapshot() { return chain_.TaskSnapshot(); }
std::set<const Variable*> GetLiveVariables() {
return chain_.GetLiveVariables();
}
bool IsDeclaredInCurrentScope(const std::string& name);
Statement* next_body() const { return next_body_; }
......
......@@ -18,7 +18,6 @@ class GlobalContext;
class Scope;
class TypeOracle;
class Builtin;
class Label;
class Module {
public:
......@@ -69,10 +68,6 @@ class GlobalContext {
friend class BreakContinueActivator;
Callable* GetCurrentCallable() const { return current_callable_; }
Block* GetCurrentBreak() const { return break_continue_stack_.back().first; }
Block* GetCurrentContinue() const {
return break_continue_stack_.back().second;
}
Declarations* declarations() { return &declarations_; }
Ast* ast() { return &ast_; }
......@@ -82,7 +77,6 @@ class GlobalContext {
int next_label_number_;
Declarations declarations_;
Callable* current_callable_;
std::vector<std::pair<Block*, Block*>> break_continue_stack_;
std::map<std::string, std::unique_ptr<Module>> modules_;
Module* default_module_;
Ast ast_;
......@@ -106,19 +100,6 @@ class CurrentCallableActivator {
Declarations::NodeScopeActivator scope_activator_;
};
class BreakContinueActivator {
public:
BreakContinueActivator(GlobalContext& context, Block* break_block,
Block* continue_block)
: context_(context) {
context_.break_continue_stack_.push_back({break_block, continue_block});
}
~BreakContinueActivator() { context_.break_continue_stack_.pop_back(); }
private:
GlobalContext& context_;
};
} // namespace torque
} // namespace internal
} // namespace v8
......
This diff is collapsed.
......@@ -104,6 +104,99 @@ class LocationReference {
LocationReference() = default;
};
template <class T>
class Binding;
template <class T>
class BindingsManager {
public:
base::Optional<Binding<T>*> TryLookup(const std::string& name) {
return current_bindings_[name];
}
private:
friend class Binding<T>;
std::unordered_map<std::string, base::Optional<Binding<T>*>>
current_bindings_;
};
template <class T>
class Binding : public T {
public:
template <class... Args>
Binding(BindingsManager<T>* manager, const std::string& name, Args&&... args)
: T(std::forward<Args>(args)...),
manager_(manager),
name_(name),
previous_binding_(this) {
std::swap(previous_binding_, manager_->current_bindings_[name]);
}
~Binding() { manager_->current_bindings_[name_] = previous_binding_; }
const std::string& name() const { return name_; }
SourcePosition declaration_position() const { return declaration_position_; }
private:
BindingsManager<T>* manager_;
const std::string name_;
base::Optional<Binding*> previous_binding_;
SourcePosition declaration_position_ = CurrentSourcePosition::Get();
DISALLOW_COPY_AND_MOVE_AND_ASSIGN(Binding);
};
template <class T>
class BlockBindings {
public:
explicit BlockBindings(BindingsManager<T>* manager) : manager_(manager) {}
void Add(std::string name, T value) {
for (const auto& binding : bindings_) {
if (binding->name() == name) {
ReportError(
"redeclaration of name \"", name,
"\" in the same block is illegal, previous declaration at: ",
binding->declaration_position());
}
}
bindings_.push_back(base::make_unique<Binding<T>>(manager_, std::move(name),
std::move(value)));
}
std::vector<Binding<T>*> bindings() const {
std::vector<Binding<T>*> result;
result.reserve(bindings_.size());
for (auto& b : bindings_) {
result.push_back(b.get());
}
return result;
}
private:
BindingsManager<T>* manager_;
std::vector<std::unique_ptr<Binding<T>>> bindings_;
};
struct LocalValue {
bool is_const;
VisitResult value;
};
struct LocalLabel {
Block* block;
std::vector<const Type*> parameter_types;
explicit LocalLabel(Block* block,
std::vector<const Type*> parameter_types = {})
: block(block), parameter_types(std::move(parameter_types)) {}
};
struct Arguments {
VisitResultVector parameters;
std::vector<Binding<LocalLabel>*> labels;
};
bool IsCompatibleSignature(const Signature& sig, const TypeVector& types,
const std::vector<Binding<LocalLabel>*>& labels);
class ImplementationVisitor : public FileVisitor {
public:
explicit ImplementationVisitor(GlobalContext& global_context)
......@@ -188,6 +281,8 @@ class ImplementationVisitor : public FileVisitor {
const Type* Visit(ContinueStatement* stmt);
const Type* Visit(ForLoopStatement* stmt);
const Type* Visit(VarDeclarationStatement* stmt);
const Type* Visit(VarDeclarationStatement* stmt,
BlockBindings<LocalValue>* block_bindings);
const Type* Visit(ForOfLoopStatement* stmt);
const Type* Visit(BlockStatement* block);
const Type* Visit(ExpressionStatement* stmt);
......@@ -199,6 +294,19 @@ class ImplementationVisitor : public FileVisitor {
void GenerateImplementation(const std::string& dir, Module* module);
DECLARE_CONTEXTUAL_VARIABLE(ValueBindingsManager,
BindingsManager<LocalValue>);
DECLARE_CONTEXTUAL_VARIABLE(LabelBindingsManager,
BindingsManager<LocalLabel>);
// A BindingsManagersScope has to be active for local bindings to be created.
// Shadowing an existing BindingsManagersScope by creating a new one hides all
// existing bindings while the additional BindingsManagersScope is active.
struct BindingsManagersScope {
ValueBindingsManager::Scope value_bindings_manager;
LabelBindingsManager::Scope label_bindings_manager;
};
private:
std::string GetBaseAssemblerName(Module* module);
......@@ -224,8 +332,8 @@ class ImplementationVisitor : public FileVisitor {
base_ = visitor_->assembler().CurrentStack().AboveTop();
}
VisitResult Yield(VisitResult result) {
DCHECK(!yield_called_);
yield_called_ = true;
DCHECK(!closed_);
closed_ = true;
if (!result.IsOnStack()) {
if (!visitor_->assembler().CurrentBlockIsComplete()) {
visitor_->assembler().DropTo(base_);
......@@ -243,22 +351,48 @@ class ImplementationVisitor : public FileVisitor {
result.stack_range().Size()));
}
void Close() {
DCHECK(!closed_);
closed_ = true;
if (!visitor_->assembler().CurrentBlockIsComplete()) {
visitor_->assembler().DropTo(base_);
}
}
~StackScope() {
if (yield_called_) {
if (closed_) {
DCHECK_IMPLIES(
!visitor_->assembler().CurrentBlockIsComplete(),
base_ == visitor_->assembler().CurrentStack().AboveTop());
} else if (!visitor_->assembler().CurrentBlockIsComplete()) {
visitor_->assembler().DropTo(base_);
} else {
Close();
}
}
private:
ImplementationVisitor* visitor_;
BottomOffset base_;
bool yield_called_ = false;
bool closed_ = false;
};
class BreakContinueActivator {
public:
BreakContinueActivator(Block* break_block, Block* continue_block)
: break_binding_{&LabelBindingsManager::Get(), "_break",
LocalLabel{break_block}},
continue_binding_{&LabelBindingsManager::Get(), "_continue",
LocalLabel{continue_block}} {}
private:
Binding<LocalLabel> break_binding_;
Binding<LocalLabel> continue_binding_;
};
base::Optional<Binding<LocalValue>*> TryLookupLocalValue(
const std::string& name);
base::Optional<Binding<LocalLabel>*> TryLookupLabel(const std::string& name);
Binding<LocalLabel>* LookupLabel(const std::string& name);
Block* LookupSimpleLabel(const std::string& name);
Callable* LookupCall(const std::string& name, const Arguments& arguments,
const TypeVector& specialization_types);
......@@ -276,17 +410,11 @@ class ImplementationVisitor : public FileVisitor {
VisitResult GeneratePointerCall(Expression* callee,
const Arguments& parameters, bool tail_call);
bool GenerateLabeledStatementBlocks(
const std::vector<Statement*>& blocks,
const std::vector<Label*>& statement_labels, Block* merge_block);
void GenerateBranch(const VisitResult& condition, Block* true_block,
Block* false_block);
void GenerateBranch(const VisitResult& condition, Label* true_label,
Label* false_label);
bool GenerateExpressionBranch(Expression* expression,
const std::vector<Label*>& statement_labels,
const std::vector<Statement*>& statement_blocks,
Block* merge_block);
void GenerateExpressionBranch(Expression* expression, Block* true_block,
Block* false_block);
void GenerateMacroFunctionDeclaration(std::ostream& o,
const std::string& macro_prefix,
......@@ -307,20 +435,19 @@ class ImplementationVisitor : public FileVisitor {
Visit(callable, MakeSignature(signature), body);
}
void CreateBlockForLabel(Label* label, Stack<const Type*> stack);
void GenerateLabelBind(Label* label);
StackRange GenerateLabelGoto(Label* label,
StackRange GenerateLabelGoto(LocalLabel* label,
base::Optional<StackRange> arguments = {});
std::vector<Label*> LabelsFromIdentifiers(
std::vector<Binding<LocalLabel>*> LabelsFromIdentifiers(
const std::vector<std::string>& names);
StackRange LowerParameter(const Type* type, const std::string& parameter_name,
Stack<std::string>* lowered_parameters);
std::string ExternalLabelParameterName(Label* label, size_t i);
std::string ExternalLabelName(const std::string& label_name);
std::string ExternalLabelParameterName(const std::string& label_name,
size_t i);
std::string ExternalParameterName(const std::string& name);
std::ostream& source_out() { return module_->source_stream(); }
......
......@@ -25,14 +25,6 @@ Scope* ScopeChain::NewScope() {
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));
}
}
}
void Scope::Print() {
std::cout << "scope #" << std::to_string(scope_number_) << "\n";
for (auto& i : lookup_) {
......
......@@ -17,7 +17,6 @@ namespace internal {
namespace torque {
class ScopeChain;
class Variable;
class Declarable;
class Scope {
......@@ -36,8 +35,6 @@ class Scope {
ScopeChain& GetScopeChain() const { return scope_chain_; }
void AddLiveVariables(std::set<const Variable*>& set);
void Print();
class Activator;
......@@ -86,14 +83,6 @@ class ScopeChain {
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);
}
......
......@@ -5,6 +5,8 @@
#ifndef V8_TORQUE_SOURCE_POSITIONS_H_
#define V8_TORQUE_SOURCE_POSITIONS_H_
#include <iostream>
#include "src/torque/contextual.h"
namespace v8 {
......@@ -48,6 +50,10 @@ inline std::string PositionAsString(SourcePosition pos) {
std::to_string(pos.line + 1) + ":" + std::to_string(pos.column + 1);
}
inline std::ostream& operator<<(std::ostream& out, SourcePosition pos) {
return out << PositionAsString(pos);
}
} // namespace torque
} // namespace internal
} // namespace v8
......
......@@ -192,6 +192,7 @@ void LintGenericParameters(const GenericParameters& parameters) {
}
void CheckNotDeferredStatement(Statement* statement) {
CurrentSourcePosition::Scope source_position(statement->pos);
if (BlockStatement* block = BlockStatement::DynamicCast(statement)) {
if (block->deferred) {
LintError(
......@@ -585,6 +586,11 @@ base::Optional<ParseResult> MakeIfStatement(
ReportError("if-else statements require curly braces");
}
if (is_constexpr) {
CheckNotDeferredStatement(if_true);
if (if_false) CheckNotDeferredStatement(*if_false);
}
Statement* result =
MakeNode<IfStatement>(is_constexpr, condition, if_true, if_false);
return ParseResult{result};
......@@ -747,6 +753,9 @@ base::Optional<ParseResult> MakeBlockStatement(
ParseResultIterator* child_results) {
auto deferred = child_results->NextAs<bool>();
auto statements = child_results->NextAs<std::vector<Statement*>>();
for (Statement* statement : statements) {
CheckNotDeferredStatement(statement);
}
Statement* result = MakeNode<BlockStatement>(deferred, std::move(statements));
return ParseResult{result};
}
......@@ -782,9 +791,12 @@ base::Optional<ParseResult> MakeForLoopStatement(
auto var_decl = child_results->NextAs<base::Optional<Statement*>>();
auto test = child_results->NextAs<base::Optional<Expression*>>();
auto action = child_results->NextAs<base::Optional<Expression*>>();
base::Optional<Statement*> action_stmt;
if (action) action_stmt = MakeNode<ExpressionStatement>(*action);
auto body = child_results->NextAs<Statement*>();
CheckNotDeferredStatement(body);
Statement* result = MakeNode<ForLoopStatement>(var_decl, test, action, body);
Statement* result =
MakeNode<ForLoopStatement>(var_decl, test, action_stmt, body);
return ParseResult{result};
}
......
......@@ -280,27 +280,6 @@ bool IsAssignableFrom(const Type* to, const Type* from) {
return TypeOracle::IsImplicitlyConvertableFrom(to, from);
}
bool IsCompatibleSignature(const Signature& sig, const TypeVector& types,
const std::vector<Label*>& labels) {
auto i = sig.parameter_types.types.begin() + sig.implicit_count;
if ((sig.parameter_types.types.size() - sig.implicit_count) > types.size())
return false;
// TODO(danno): The test below is actually insufficient. The labels'
// parameters must be checked too. ideally, the named part of
// LabelDeclarationVector would be factored out so that the label count and
// parameter types could be passed separately.
if (sig.labels.size() != labels.size()) return false;
for (auto current : types) {
if (i == sig.parameter_types.types.end()) {
if (!sig.parameter_types.var_args) return false;
if (!IsAssignableFrom(TypeOracle::GetObjectType(), current)) return false;
} else {
if (!IsAssignableFrom(*i++, current)) return false;
}
}
return true;
}
bool operator<(const Type& a, const Type& b) {
return a.MangledName() < b.MangledName();
}
......
......@@ -32,7 +32,6 @@ static const char* const CONST_INT31_TYPE_STRING = "constexpr int31";
static const char* const CONST_INT32_TYPE_STRING = "constexpr int32";
static const char* const CONST_FLOAT64_TYPE_STRING = "constexpr float64";
class Label;
class Value;
class Module;
......@@ -443,17 +442,10 @@ struct Signature {
}
};
struct Arguments {
VisitResultVector parameters;
std::vector<Label*> labels;
};
void PrintSignature(std::ostream& os, const Signature& sig, bool with_names);
std::ostream& operator<<(std::ostream& os, const Signature& sig);
bool IsAssignableFrom(const Type* to, const Type* from);
bool IsCompatibleSignature(const Signature& sig, const TypeVector& types,
const std::vector<Label*>& labels);
TypeVector LowerType(const Type* type);
size_t LoweredSlotCount(const Type* type);
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment