summaryrefslogtreecommitdiff
path: root/tiger-compiler/src/escapes
diff options
context:
space:
mode:
Diffstat (limited to 'tiger-compiler/src/escapes')
-rw-r--r--tiger-compiler/src/escapes/escapes-visitor.cc31
-rw-r--r--tiger-compiler/src/escapes/escapes-visitor.hh75
-rw-r--r--tiger-compiler/src/escapes/libescapes.cc23
-rw-r--r--tiger-compiler/src/escapes/libescapes.hh23
-rw-r--r--tiger-compiler/src/escapes/local.am7
-rw-r--r--tiger-compiler/src/escapes/tasks.cc38
-rw-r--r--tiger-compiler/src/escapes/tasks.hh28
7 files changed, 225 insertions, 0 deletions
diff --git a/tiger-compiler/src/escapes/escapes-visitor.cc b/tiger-compiler/src/escapes/escapes-visitor.cc
new file mode 100644
index 0000000..f0fd5e2
--- /dev/null
+++ b/tiger-compiler/src/escapes/escapes-visitor.cc
@@ -0,0 +1,31 @@
+/**
+ ** \file escapes/escapes-visitor.cc
+ ** \brief Implementation for escapes/escapes-visitor.hh.
+ */
+
+#include <ast/all.hh>
+#include <escapes/escapes-visitor.hh>
+#include <misc/contract.hh>
+
+namespace escapes
+{
+ // FIXME DONE: Some code was deleted here.
+
+ void EscapesVisitor::operator()(ast::SimpleVar& e)
+ {
+ if (depth_map_.at(e.def_get()) < current_depth_)
+ e.def_get()->escape_set(true);
+ }
+ void EscapesVisitor::operator()(ast::VarDec& e)
+ {
+ e.escape_set(false);
+ depth_map_.insert_or_assign(&e, current_depth_);
+ super_type::operator()(e);
+ }
+ void EscapesVisitor::operator()(ast::FunctionDec& e)
+ {
+ current_depth_++;
+ super_type::operator()(e);
+ current_depth_--;
+ }
+} // namespace escapes
diff --git a/tiger-compiler/src/escapes/escapes-visitor.hh b/tiger-compiler/src/escapes/escapes-visitor.hh
new file mode 100644
index 0000000..3b4023f
--- /dev/null
+++ b/tiger-compiler/src/escapes/escapes-visitor.hh
@@ -0,0 +1,75 @@
+/**
+ ** \file escapes/escapes-visitor.hh
+ ** \brief Compute the escapes.
+ **
+ ** Variables and formals of a function may escape, i.e., be accessed
+ ** by an inner function.
+ **
+ ** When the semantic analysis finds a declaration of variable or
+ ** formal FOO, it needs to know whether it escapes or not. This
+ ** requires an additional pass, before the semantic analysis, just to
+ ** spot the potential escapes of FOO.
+ **
+ ** In order to pass the result to the semantic analysis which walks
+ ** across the ast, the most natural and easy solution consists in
+ ** tagging the various VarDec and Field.
+ **
+ ** Now, how shall we compute the escapes?
+ ** The answer is obvious: we need to walk the ast, searching for variables
+ ** declared then accessed by an inner function.
+ **
+ ** If a variable is accessed from a nested function
+ **
+ ** 2è possibilité :
+ ** - Aucune n'échappe
+ ** - Echappe si accessed dans une fonction nestée
+ ** Attention
+ */
+
+#pragma once
+
+#include <map>
+
+#include <ast/default-visitor.hh>
+#include <ast/non-assert-visitor.hh>
+#include <ast/non-object-visitor.hh>
+
+namespace escapes
+{
+ /** \brief Compute the escapes.
+ **
+ ** The EscapeVisitor is extremely similar to type::TypeChecker:
+ ** in its course of operation it must relate uses to
+ ** definitions. Therefore it will be run after the bind::Binder.
+ ** It also needs auxiliary information about the definitions (their
+ ** depth): a simple map suffices, since scoping issues were handled
+ ** by the bind::Binder.
+ **
+ ** Note that this EscapesVisitor is mainly doing nothing: it is just
+ ** interested in declaration and uses of variables/formals (and, of
+ ** course, function declaration...). It would be somewhat stupid to
+ ** write all the methods that `do nothing but walk'. This is why we
+ ** will inherit from the non const ast::DefaultVisitor.
+ **/
+ class EscapesVisitor
+ : public ast::DefaultVisitor
+ , public ast::NonObjectVisitor
+ , public ast::NonAssertVisitor
+ {
+ public:
+ /// Super class type.
+ using super_type = ast::DefaultVisitor;
+ /// Import all the overloaded visit methods.
+ using super_type::operator();
+
+ // FIXME DONE: Some code was deleted here.
+ void operator()(ast::SimpleVar& e) override;
+ void operator()(ast::VarDec& e) override;
+ void operator()(ast::FunctionDec& e) override;
+ protected:
+ std::map<ast::VarDec*, size_t> depth_map_;
+ private:
+ size_t current_depth_ = 0;
+ };
+
+} // namespace escapes
diff --git a/tiger-compiler/src/escapes/libescapes.cc b/tiger-compiler/src/escapes/libescapes.cc
new file mode 100644
index 0000000..6124d54
--- /dev/null
+++ b/tiger-compiler/src/escapes/libescapes.cc
@@ -0,0 +1,23 @@
+/**
+ ** \file escapes/libescapes.cc
+ ** \brief Define exported escapes functions.
+ */
+
+#include <escapes/escapes-visitor.hh>
+#include <escapes/libescapes.hh>
+
+namespace escapes
+{
+ /** Walk the tree, and set the escape flag of variables and arguments
+ if they do escape. */
+ void escapes_compute(ast::Ast& tree)
+ {
+ /// boolean to check if an escapes pass was done in desugar
+ escapes::escaped = true;
+ EscapesVisitor escapes_compute;
+ escapes_compute(tree);
+ }
+
+ bool escaped = false;
+
+} // namespace escapes
diff --git a/tiger-compiler/src/escapes/libescapes.hh b/tiger-compiler/src/escapes/libescapes.hh
new file mode 100644
index 0000000..2d3dd73
--- /dev/null
+++ b/tiger-compiler/src/escapes/libescapes.hh
@@ -0,0 +1,23 @@
+/**
+ ** \file escapes/libescapes.hh
+ ** \brief Declare functions and variables exported by escapes module.
+ */
+
+#pragma once
+
+#include <ast/fwd.hh>
+#include <misc/error.hh>
+
+/// Computing escape and static link related information.
+namespace escapes
+{
+ /// Compute the escaping variables.
+ void escapes_compute(ast::Ast& tree);
+
+ /// This boolean is used to know whether escape pass
+ /// was made
+ /// FIXME: this is a dirty fix it should be replaced with a
+ /// new implementation of tasks
+ extern bool escaped;
+
+} // namespace escapes
diff --git a/tiger-compiler/src/escapes/local.am b/tiger-compiler/src/escapes/local.am
new file mode 100644
index 0000000..ab6c63a
--- /dev/null
+++ b/tiger-compiler/src/escapes/local.am
@@ -0,0 +1,7 @@
+## escape module.
+
+src_libtc_la_SOURCES += \
+ %D%/libescapes.hh %D%/libescapes.cc \
+ %D%/escapes-visitor.hh %D%/escapes-visitor.cc
+
+TASKS += %D%/tasks.hh %D%/tasks.cc
diff --git a/tiger-compiler/src/escapes/tasks.cc b/tiger-compiler/src/escapes/tasks.cc
new file mode 100644
index 0000000..42e6919
--- /dev/null
+++ b/tiger-compiler/src/escapes/tasks.cc
@@ -0,0 +1,38 @@
+/**
+ ** \file escapes/tasks.cc
+ ** \brief Escapes module related tasks' implementation.
+ */
+
+#include <ostream>
+
+#include <ast/libast.hh>
+#include <ast/tasks.hh>
+#include <escapes/libescapes.hh>
+#define DEFINE_TASKS 1
+#include <escapes/tasks.hh>
+#undef DEFINE_TASKS
+#include <misc/xalloc.hh>
+
+namespace escapes::tasks
+{
+
+ /*--------------------.
+ | Static Link tasks. |
+ `--------------------*/
+
+ void escapes_compute() { escapes::escapes_compute(*ast::tasks::the_program); }
+
+ /* WARNING. It is very tempting to use BOOLEAN_TASK_DECLARE with
+ these stream flags, since it factors out the need for the
+ following routines. Unfortunately when the Tasks are created,
+ not all the misc::xalloc are instantiated, so the registered
+ address of these flags is likely to change if there are other
+ xalloc in between. It is the index that is constant, not the
+ address of the pword.
+
+ Of course we could have Tasks dedicated to misc::xalloc, but
+ that's not nice. */
+
+ void escapes_display() { ast::escapes_display(std::cout) = true; }
+
+} // namespace escapes::tasks
diff --git a/tiger-compiler/src/escapes/tasks.hh b/tiger-compiler/src/escapes/tasks.hh
new file mode 100644
index 0000000..636c13f
--- /dev/null
+++ b/tiger-compiler/src/escapes/tasks.hh
@@ -0,0 +1,28 @@
+/**
+ ** \file escapes/tasks.hh
+ ** \brief Escapes module related tasks.
+ */
+
+#pragma once
+
+#include <task/libtask.hh>
+
+/// The Tasks of the escapes module.
+namespace escapes::tasks
+{
+ TASK_GROUP("3. Escapes");
+
+ /// Compute variables escaping.
+ TASK_DECLARE("e|escapes-compute",
+ "compute the escaping variables "
+ "and the functions requiring a static link",
+ escapes_compute,
+ "bound");
+
+ /// Display escaped variables.
+ TASK_DECLARE("E|escapes-display",
+ "enable escape display in the AST",
+ escapes_display,
+ "parse");
+
+} // namespace escapes::tasks