summaryrefslogtreecommitdiff
path: root/src/SDCCbtree.cc
diff options
context:
space:
mode:
authorXavier ASUS <xavi92psx@gmail.com>2019-10-18 00:31:54 +0200
committerXavier ASUS <xavi92psx@gmail.com>2019-10-18 00:31:54 +0200
commit268a53de823a6750d6256ee1fb1e7707b4b45740 (patch)
tree42c1799a9a82b2f7d9790ee9fe181d72a7274751 /src/SDCCbtree.cc
downloadsdcc-gas-268a53de823a6750d6256ee1fb1e7707b4b45740.tar.gz
sdcc-3.9.0 fork implementing GNU assembler syntax
This fork aims to provide better support for stm8-binutils
Diffstat (limited to 'src/SDCCbtree.cc')
-rw-r--r--src/SDCCbtree.cc172
1 files changed, 172 insertions, 0 deletions
diff --git a/src/SDCCbtree.cc b/src/SDCCbtree.cc
new file mode 100644
index 0000000..8266cfb
--- /dev/null
+++ b/src/SDCCbtree.cc
@@ -0,0 +1,172 @@
+// Philipp Klaus Krause, philipp@informatik.uni-frankfurt.de, pkk@spth.de, 2011
+//
+// (c) 2011 Goethe-Universität Frankfurt
+//
+// This program is free software; you can redistribute it and/or modify it
+// under the terms of the GNU General Public License as published by the
+// Free Software Foundation; either version 2, or (at your option) any
+// later version.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with this program; if not, write to the Free Software
+// Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+
+#include <set>
+#include <map>
+#include <iostream>
+
+#include <boost/graph/adjacency_list.hpp>
+
+#include "common.h"
+
+extern "C"
+{
+#include "SDCCbtree.h"
+}
+
+#undef BTREE_DEBUG
+
+typedef boost::adjacency_list<boost::vecS, boost::vecS, boost::bidirectionalS, std::pair<std::set<symbol *>, int> > btree_t;
+
+typedef std::map<int, btree_t::vertex_descriptor> bmap_t;
+typedef std::map<btree_t::vertex_descriptor, int> bmaprev_t;
+
+static btree_t btree;
+static bmap_t bmap;
+static bmaprev_t bmaprev;
+
+void btree_clear_subtree(btree_t::vertex_descriptor v)
+{
+ btree[v].first.clear();
+
+ boost::graph_traits<btree_t>::out_edge_iterator e, e_end;
+ for(boost::tie(e, e_end) = boost::out_edges(v, btree); e != e_end; ++e)
+ btree_clear_subtree(boost::target(*e, btree));
+}
+
+void btree_clear(void)
+{
+#ifdef BTREE_DEBUG
+ std::cout << "Clearing.\n"; std::cout.flush();
+#endif
+ btree_clear_subtree(0);
+}
+
+void btree_add_child(short parent, short child)
+{
+#ifdef BTREE_DEBUG
+ std::cout << "Adding child " << child << " at parent " << parent << "\n"; std::cout.flush();
+#endif
+
+ if(!boost::num_vertices(btree))
+ {
+ boost::add_vertex(btree);
+ bmap[0] = 0;
+ bmaprev[0] = 0;
+ }
+
+ wassert(parent != child);
+ wassert(bmap.find(parent) != bmap.end());
+
+ btree_t::vertex_descriptor c = boost::add_vertex(btree);
+ bmap[child] = c;
+ bmaprev[c] = child;
+
+ wassert(bmap[parent] != c);
+
+ boost::add_edge(bmap[parent], c, btree);
+}
+
+static btree_t::vertex_descriptor btree_lowest_common_ancestor_impl(btree_t::vertex_descriptor a, btree_t::vertex_descriptor b)
+{
+ if(a == b)
+ return(a);
+ else if (a > b)
+ a = boost::source(*boost::in_edges(a, btree).first, btree);
+ else // (a < b)
+ b = boost::source(*boost::in_edges(b, btree).first, btree);
+
+ return(btree_lowest_common_ancestor(a, b));
+}
+
+short btree_lowest_common_ancestor(short a, short b)
+{
+ return(bmaprev[btree_lowest_common_ancestor_impl(bmap[a], bmap[b])]);
+}
+
+void btree_add_symbol(struct symbol *s)
+{
+ int block;
+ wassert(s);
+ block = s->_isparm ? 0 : s->block; // This is essentially a workaround. TODO: Ensure that the parameter block is placed correctly in the btree instead!
+
+#ifdef BTREE_DEBUG
+ std::cout << "Adding symbol " << s->name << " at " << block << "\n";
+#endif
+
+ wassert(bmap.find(block) != bmap.end());
+ wassert(bmap[block] < boost::num_vertices(btree));
+ btree[bmap[block]].first.insert(s);
+}
+
+static void btree_alloc_subtree(btree_t::vertex_descriptor v, int sPtr, int cssize, int *ssize)
+{
+ std::set<symbol *>::iterator s, s_end;
+ wassert(v < boost::num_vertices(btree));
+ for(s = btree[v].first.begin(), s_end = btree[v].first.end(); s != s_end; ++s)
+ {
+ struct symbol *const sym = *s;
+ const int size = getSize (sym->type);
+
+#ifdef BTREE_DEBUG
+ std::cout << "Allocating symbol " << sym->name << " (" << v << ") of size " << size << " to " << sPtr << "\n";
+#endif
+
+ if(port->stack.direction > 0)
+ {
+ SPEC_STAK (sym->etype) = sym->stack = (sPtr + !TARGET_PDK_LIKE);
+ sPtr += size;
+ }
+ else
+ {
+ sPtr -= size;
+ SPEC_STAK (sym->etype) = sym->stack = sPtr;
+ }
+
+ cssize += size;
+ }
+ btree[v].second = cssize;
+ if(cssize > *ssize)
+ *ssize = cssize;
+
+ boost::graph_traits<btree_t>::out_edge_iterator e, e_end;
+ for(boost::tie(e, e_end) = boost::out_edges(v, btree); e != e_end; ++e)
+ btree_alloc_subtree(boost::target(*e, btree), sPtr, cssize, ssize);
+}
+
+void btree_alloc(void)
+{
+ int ssize = 0;
+
+ if(!boost::num_vertices(btree))
+ return;
+
+ btree_alloc_subtree(0, 0, 0, &ssize);
+
+ if(currFunc)
+ {
+#ifdef BTREE_DEBUG
+ std::cout << "btree stack allocation used total of " << ssize << " bytes\n";
+#endif
+ if (TARGET_PDK_LIKE) // Stack pointer needs to be aligned to multiple of 2
+ if (ssize & 1) ssize++;
+ currFunc->stack += ssize;
+ SPEC_STAK (currFunc->etype) += ssize;
+ }
+}
+