diff --git a/gcc/rust/analysis/rust-type-resolution.cc b/gcc/rust/analysis/rust-type-resolution.cc index 5500fafbf5ee2..541acd00d8f92 100644 --- a/gcc/rust/analysis/rust-type-resolution.cc +++ b/gcc/rust/analysis/rust-type-resolution.cc @@ -466,7 +466,17 @@ void TypeResolution::visit (AST::ArrayExpr &expr) { auto elements = expr.get_internal_elements (); + + auto before = typeBuffer.size (); elements->accept_vis (*this); + if (typeBuffer.size () <= before) + { + rust_error_at (expr.get_locus_slow (), + "unable to determine type for ArrayExpr"); + return; + } + + expr.set_inferred_type (typeBuffer.back ()); } void diff --git a/gcc/rust/ast/rust-expr.h b/gcc/rust/ast/rust-expr.h index d3e7cbdc86ae9..49710419266b6 100644 --- a/gcc/rust/ast/rust-expr.h +++ b/gcc/rust/ast/rust-expr.h @@ -1000,6 +1000,10 @@ class ArrayExpr : public ExprWithoutBlock Location locus; + // this is a reference to what the inferred type is based on + // this init expression + Type *inferredType; + public: std::string as_string () const override; @@ -1050,6 +1054,9 @@ class ArrayExpr : public ExprWithoutBlock ArrayElems *get_internal_elements () { return internal_elements.get (); }; + Type *get_inferred_type () { return inferredType; } + void set_inferred_type (Type *type) { inferredType = type; } + protected: /* Use covariance to implement clone function as returning this object rather * than base */ diff --git a/gcc/rust/ast/rust-type.h b/gcc/rust/ast/rust-type.h index 301b66472db4b..089aaeb5470b7 100644 --- a/gcc/rust/ast/rust-type.h +++ b/gcc/rust/ast/rust-type.h @@ -576,6 +576,10 @@ class ArrayType : public TypeNoBounds Type *get_element_type () { return elem_type.get (); } + Expr *get_size_expr () { return size.get (); } + + Location &get_locus () { return locus; } + protected: /* Use covariance to implement clone function as returning this object rather * than base */ diff --git a/gcc/rust/backend/rust-compile.cc b/gcc/rust/backend/rust-compile.cc index 0b632b72be199..2dbce169f0409 100644 --- a/gcc/rust/backend/rust-compile.cc +++ b/gcc/rust/backend/rust-compile.cc @@ -503,19 +503,102 @@ Compilation::visit (AST::CompoundAssignmentExpr &expr) void Compilation::visit (AST::GroupedExpr &expr) {} -// void Compilation::visit(ArrayElems& elems) {} + void Compilation::visit (AST::ArrayElemsValues &elems) -{} +{ + std::vector< ::Bexpression *> elements; + + bool failed = false; + elems.iterate ([&] (AST::Expr *expr) mutable -> bool { + Bexpression *value = nullptr; + VISIT_POP (expr.get_locus_slow (), expr, value, exprs); + if (value == nullptr) + { + rust_fatal_error (expr->get_locus_slow (), + "failed to compile value to array initialiser"); + return false; + } + elements.push_back (value); + return true; + }); + + // nothing to do when its failed + if (failed) + return; + + arrayConsStack.push_back (elements); +} + void Compilation::visit (AST::ArrayElemsCopied &elems) {} + void Compilation::visit (AST::ArrayExpr &expr) -{} +{ + translatedType = nullptr; + expr.get_inferred_type ()->accept_vis (*this); + if (translatedType == nullptr) + { + rust_error_at (expr.get_locus_slow (), + "failed to compile array type for ArrayExpr"); + return; + } + + ::Btype *compiledType = translatedType; + translatedType = nullptr; + + auto before = arrayConsStack.size (); + expr.get_internal_elements ()->accept_vis (*this); + if (arrayConsStack.size () <= before) + { + rust_error_at (expr.get_locus_slow (), + "failed to compile the array constructor"); + return; + } + std::vector< ::Bexpression *> initializer = arrayConsStack.back (); + arrayConsStack.pop_back (); + + std::vector indexes; + for (unsigned long i = 0; i < initializer.size (); ++i) + indexes.push_back (i); + + Bexpression *cons + = backend->array_constructor_expression (compiledType, indexes, initializer, + expr.get_locus_slow ()); + exprs.push_back (cons); +} + void Compilation::visit (AST::ArrayIndexExpr &expr) -{} +{ + Bexpression *arrayExpr = nullptr; + VISIT_POP (expr.get_array_expr ()->get_locus_slow (), expr.get_array_expr (), + arrayExpr, exprs); + if (arrayExpr == nullptr) + { + rust_error_at (expr.get_locus_slow (), + "failed to compile value to array expression reference"); + return; + } + + Bexpression *indexExpr = nullptr; + VISIT_POP (expr.get_index_expr ()->get_locus_slow (), expr.get_index_expr (), + indexExpr, exprs); + if (indexExpr == nullptr) + { + rust_error_at (expr.get_locus_slow (), + "failed to compile value to array index expression"); + return; + } + + Bexpression *indexExpression + = backend->array_index_expression (arrayExpr, indexExpr, + expr.get_locus_slow ()); + exprs.push_back (indexExpression); +} + void Compilation::visit (AST::TupleExpr &expr) {} @@ -1376,9 +1459,34 @@ Compilation::visit (AST::RawPointerType &type) void Compilation::visit (AST::ReferenceType &type) {} + void Compilation::visit (AST::ArrayType &type) -{} +{ + Btype *elementType; + translatedType = nullptr; + type.get_element_type ()->accept_vis (*this); + if (translatedType == nullptr) + { + rust_error_at (type.get_locus (), + "Failed to compile element type for array"); + return; + } + elementType = translatedType; + + Bexpression *length = nullptr; + VISIT_POP (type.get_size_expr ()->get_locus_slow (), type.get_size_expr (), + length, exprs); + if (length == nullptr) + { + rust_error_at (type.get_size_expr ()->get_locus_slow (), + "failed to size for array type"); + return; + } + + translatedType = backend->array_type (elementType, length); +} + void Compilation::visit (AST::SliceType &type) {} diff --git a/gcc/rust/backend/rust-compile.h b/gcc/rust/backend/rust-compile.h index ba034839f2797..88c83187a0dea 100644 --- a/gcc/rust/backend/rust-compile.h +++ b/gcc/rust/backend/rust-compile.h @@ -243,7 +243,8 @@ class Compilation : public AST::ASTVisitor std::vector< ::Bexpression *> exprs; std::vector< ::Bstatement *> stmts; std::vector< ::Bvariable *> varBuffer; - std::vector structBuffer; + std::vector structBuffer; + std::vector > arrayConsStack; // careful these are the vectors we pass into the GCC middle-end std::vector< ::Btype *> type_decls; diff --git a/gcc/testsuite/rust.test/compilable/arrays1.rs b/gcc/testsuite/rust.test/compilable/arrays1.rs new file mode 100644 index 0000000000000..f7e66af7a2661 --- /dev/null +++ b/gcc/testsuite/rust.test/compilable/arrays1.rs @@ -0,0 +1,7 @@ +fn main() { + let xs: [i32; 5] = [1, 2, 3, 4, 5]; + let xy = [6, 7, 8]; + + let a = xs[0]; + let b = xy[2]; +}