aboutsummaryrefslogtreecommitdiff
path: root/gcc/rust/rust-gcc.cc
diff options
context:
space:
mode:
Diffstat (limited to 'gcc/rust/rust-gcc.cc')
-rw-r--r--gcc/rust/rust-gcc.cc73
1 files changed, 73 insertions, 0 deletions
diff --git a/gcc/rust/rust-gcc.cc b/gcc/rust/rust-gcc.cc
index 6ea9ef3..334e9e5 100644
--- a/gcc/rust/rust-gcc.cc
+++ b/gcc/rust/rust-gcc.cc
@@ -246,6 +246,8 @@ public:
tree array_constructor_expression (tree, const std::vector<unsigned long> &,
const std::vector<tree> &, Location);
+ tree array_initializer (tree, tree, tree, tree, tree, tree *, Location);
+
tree array_index_expression (tree array, tree index, Location);
tree call_expression (tree caller, tree fn, const std::vector<tree> &args,
@@ -1694,6 +1696,77 @@ Gcc_backend::array_constructor_expression (
return ret;
}
+// Build insns to create an array, initialize all elements of the array to
+// value, and return it
+tree
+Gcc_backend::array_initializer (tree fndecl, tree block, tree array_type,
+ tree length, tree value, tree *tmp,
+ Location locus)
+{
+ std::vector<tree> stmts;
+
+ // Temporary array we initialize with the desired value.
+ tree t = NULL_TREE;
+ Bvariable *tmp_array = this->temporary_variable (fndecl, block, array_type,
+ NULL_TREE, true, locus, &t);
+ tree arr = tmp_array->get_tree (locus);
+ stmts.push_back (t);
+
+ // Temporary for the array length used for initialization loop guard.
+ Bvariable *tmp_len = this->temporary_variable (fndecl, block, size_type_node,
+ length, true, locus, &t);
+ tree len = tmp_len->get_tree (locus);
+ stmts.push_back (t);
+
+ // Temporary variable for pointer used to initialize elements.
+ tree ptr_type = this->pointer_type (TREE_TYPE (array_type));
+ tree ptr_init
+ = build1_loc (locus.gcc_location (), ADDR_EXPR, ptr_type,
+ this->array_index_expression (arr, integer_zero_node, locus));
+ Bvariable *tmp_ptr = this->temporary_variable (fndecl, block, ptr_type,
+ ptr_init, false, locus, &t);
+ tree ptr = tmp_ptr->get_tree (locus);
+ stmts.push_back (t);
+
+ // push statement list for the loop
+ std::vector<tree> loop_stmts;
+
+ // Loop exit condition:
+ // if (length == 0) break;
+ t = this->comparison_expression (ComparisonOperator::EQUAL, len,
+ this->zero_expression (TREE_TYPE (len)),
+ locus);
+
+ t = this->exit_expression (t, locus);
+ loop_stmts.push_back (t);
+
+ // Assign value to the current pointer position
+ // *ptr = value;
+ t = this->assignment_statement (build_fold_indirect_ref (ptr), value, locus);
+ loop_stmts.push_back (t);
+
+ // Move pointer to next element
+ // ptr++;
+ tree size = TYPE_SIZE_UNIT (TREE_TYPE (ptr_type));
+ t = build2 (POSTINCREMENT_EXPR, ptr_type, ptr, convert (ptr_type, size));
+ loop_stmts.push_back (t);
+
+ // Decrement loop counter.
+ // length--;
+ t = build2 (POSTDECREMENT_EXPR, TREE_TYPE (len), len,
+ convert (TREE_TYPE (len), integer_one_node));
+ loop_stmts.push_back (t);
+
+ // pop statments and finish loop
+ tree loop_body = this->statement_list (loop_stmts);
+ stmts.push_back (this->loop_expression (loop_body, locus));
+
+ // Return the temporary in the provided pointer and the statement list which
+ // initializes it.
+ *tmp = tmp_array->get_tree (locus);
+ return this->statement_list (stmts);
+}
+
// Return an expression representing ARRAY[INDEX]
tree