From: Owen Avery <[email protected]>
gcc/rust/ChangeLog:
* backend/rust-compile-asm.cc: Include "rust-ggc.h".
(chain_asm_operand): Use GGC::ChainList.
(CompileAsm::asm_construct_outputs): Likewise.
(CompileAsm::asm_construct_inputs): Likewise.
(CompileLlvmAsm::construct_operands): Likewise.
(CompileLlvmAsm::construct_clobbers): Likewise.
* util/rust-ggc.h (class ChainList): New class.
Signed-off-by: Owen Avery <[email protected]>
---
gcc/rust/backend/rust-compile-asm.cc | 34 ++++++++++++-------------
gcc/rust/util/rust-ggc.h | 38 ++++++++++++++++++++++++++++
2 files changed, 55 insertions(+), 17 deletions(-)
diff --git a/gcc/rust/backend/rust-compile-asm.cc
b/gcc/rust/backend/rust-compile-asm.cc
index be0305a6e50..2ac65bd6520 100644
--- a/gcc/rust/backend/rust-compile-asm.cc
+++ b/gcc/rust/backend/rust-compile-asm.cc
@@ -1,16 +1,16 @@
#include "rust-compile-asm.h"
#include "rust-compile-expr.h"
#include "rust-system.h"
+#include "rust-ggc.h"
namespace Rust {
namespace Compile {
-static tree
-chain_asm_operand (tree head, const char *constraint, tree value)
+static void
+chain_asm_operand (GGC::ChainList &ls, const char *constraint, tree value)
{
auto name = build_string (strlen (constraint) + 1, constraint);
- return chainon (head,
- build_tree_list (build_tree_list (NULL_TREE, name), value));
+ ls.push_back (build_tree_list (build_tree_list (NULL_TREE, name), value));
}
CompileAsm::CompileAsm (Context *ctx) : HIRCompileBase (ctx) {}
@@ -107,7 +107,7 @@ CompileAsm::asm_construct_outputs (HIR::InlineAsm &expr)
{
// TODO: Do i need to do this?
- tree head = NULL_TREE;
+ GGC::ChainList ls;
for (auto &operand : expr.get_operands ())
{
tl::optional<std::reference_wrapper<HIR::Expr>> out_expr
@@ -118,9 +118,9 @@ CompileAsm::asm_construct_outputs (HIR::InlineAsm &expr)
tree out_tree = CompileExpr::Compile (*out_expr, this->ctx);
// expects a tree list
// TODO: This assumes that the output is a register
- head = chain_asm_operand (head, "=r", out_tree);
+ chain_asm_operand (ls, "=r", out_tree);
}
- return head;
+ return ls.get_head ();
}
tl::optional<std::reference_wrapper<HIR::Expr>>
@@ -147,7 +147,8 @@ tree
CompileAsm::asm_construct_inputs (HIR::InlineAsm &expr)
{
// TODO: Do i need to do this?
- tree head = NULL_TREE;
+
+ GGC::ChainList ls;
for (auto &operand : expr.get_operands ())
{
tl::optional<std::reference_wrapper<HIR::Expr>> in_expr
@@ -158,9 +159,9 @@ CompileAsm::asm_construct_inputs (HIR::InlineAsm &expr)
tree in_tree = CompileExpr::Compile (*in_expr, this->ctx);
// expects a tree list
// TODO: This assumes that the input is a register
- head = chain_asm_operand (head, "r", in_tree);
+ chain_asm_operand (ls, "r", in_tree);
}
- return head;
+ return ls.get_head ();
}
tree
@@ -182,29 +183,28 @@ CompileLlvmAsm::CompileLlvmAsm (Context *ctx) :
HIRCompileBase (ctx) {}
tree
CompileLlvmAsm::construct_operands (std::vector<HIR::LlvmOperand> operands)
{
- tree head = NULL_TREE;
+ GGC::ChainList ls;
for (auto &operand : operands)
{
tree t = CompileExpr::Compile (*operand.expr, this->ctx);
auto name = build_string (operand.constraint.size () + 1,
operand.constraint.c_str ());
- head = chainon (head,
- build_tree_list (build_tree_list (NULL_TREE, name), t));
+ ls.push_back (build_tree_list (build_tree_list (NULL_TREE, name), t));
}
- return head;
+ return ls.get_head ();
}
tree
CompileLlvmAsm::construct_clobbers (std::vector<AST::TupleClobber> clobbers)
{
- tree head = NULL_TREE;
+ GGC::ChainList ls;
for (auto &clobber : clobbers)
{
auto name
= build_string (clobber.symbol.size () + 1, clobber.symbol.c_str ());
- head = chainon (head, build_tree_list (NULL_TREE, name));
+ ls.push_back (build_tree_list (NULL_TREE, name));
}
- return head;
+ return ls.get_head ();
}
tree
diff --git a/gcc/rust/util/rust-ggc.h b/gcc/rust/util/rust-ggc.h
index e4ebabd412c..eb4b327fb9a 100644
--- a/gcc/rust/util/rust-ggc.h
+++ b/gcc/rust/util/rust-ggc.h
@@ -60,6 +60,44 @@ operator== (const std::string &a, const Ident &b)
return b == a;
}
+class ChainList
+{
+ tree head;
+ tree *tail_cdr;
+
+public:
+ ChainList () : head (NULL_TREE), tail_cdr (&head) {}
+
+ ChainList (ChainList &&oth)
+ {
+ head = oth.head;
+ if (oth.tail_cdr == &oth.head)
+ tail_cdr = &oth.head;
+ else
+ tail_cdr = oth.tail_cdr;
+ oth.head = NULL_TREE;
+ oth.tail_cdr = &oth.head;
+ }
+
+ ChainList &operator= (ChainList &&oth)
+ {
+ this->~ChainList ();
+ new (this) ChainList (std::move (oth));
+ return *this;
+ }
+
+ tree get_head () const { return head; }
+
+ // TREE_CHAIN (ent) will be modified
+ // making ent a node in this list
+ // do not push a single tree to multiple ChainList objects
+ void push_back (tree ent)
+ {
+ *tail_cdr = ent;
+ tail_cdr = &TREE_CHAIN (ent);
+ }
+};
+
} // namespace GGC
} // namespace Rust
--
2.50.1