From d96e1594dd378078987900819afc611bd0db19b0 Mon Sep 17 00:00:00 2001 From: Philip Herron Date: Wed, 13 Jan 2021 21:14:28 +0000 Subject: This brings in resolution and type checking of the unit-type. It is possible to assign and declare variables of unit-type which translate down to zero sized void_type_node. More work is needed to handle array and ADT types using unit-type when emiting gimple. The name+type resolution should be generic enough. --- gcc/rust/backend/rust-compile-context.h | 7 +++++-- gcc/rust/backend/rust-compile-expr.h | 15 ++++++++++----- gcc/rust/backend/rust-compile-stmt.h | 15 ++++++++++++++- gcc/rust/backend/rust-compile-tyty.h | 7 +++++-- 4 files changed, 34 insertions(+), 10 deletions(-) (limited to 'gcc/rust/backend') diff --git a/gcc/rust/backend/rust-compile-context.h b/gcc/rust/backend/rust-compile-context.h index 298ff50..5a0805b 100644 --- a/gcc/rust/backend/rust-compile-context.h +++ b/gcc/rust/backend/rust-compile-context.h @@ -223,8 +223,6 @@ public: void visit (TyTy::ErrorType &type) override { gcc_unreachable (); } - void visit (TyTy::UnitType &type) override { gcc_unreachable (); } - void visit (TyTy::InferType &type) override { gcc_unreachable (); } void visit (TyTy::FnType &type) override { gcc_unreachable (); } @@ -233,6 +231,11 @@ public: void visit (TyTy::ParamType &type) override { gcc_unreachable (); } + void visit (TyTy::UnitType &type) override + { + translated = ctx->get_backend ()->void_type (); + } + void visit (TyTy::ADTType &type) override { ::Btype *compiled_type = nullptr; diff --git a/gcc/rust/backend/rust-compile-expr.h b/gcc/rust/backend/rust-compile-expr.h index 0370129..d38ef04 100644 --- a/gcc/rust/backend/rust-compile-expr.h +++ b/gcc/rust/backend/rust-compile-expr.h @@ -38,7 +38,16 @@ public: return compiler.translated; } - virtual ~CompileExpr () {} + void visit (HIR::TupleExpr &expr) + { + if (expr.is_unit ()) + { + translated = ctx->get_backend ()->unit_expression (); + return; + } + + gcc_unreachable (); + } void visit (HIR::ReturnExpr &expr) { @@ -85,10 +94,6 @@ public: return; } - printf ("have ast node id %u ref %u for expr [%s]\n", - expr.get_mappings ().get_nodeid (), ref_node_id, - expr.as_string ().c_str ()); - // these ref_node_ids will resolve to a pattern declaration but we are // interested in the definition that this refers to get the parent id Resolver::Definition def; diff --git a/gcc/rust/backend/rust-compile-stmt.h b/gcc/rust/backend/rust-compile-stmt.h index 5f7decb..c52f605 100644 --- a/gcc/rust/backend/rust-compile-stmt.h +++ b/gcc/rust/backend/rust-compile-stmt.h @@ -71,6 +71,18 @@ public: if (!stmt.has_init_expr ()) return; + TyTy::TyBase *ty = nullptr; + if (!ctx->get_tyctx ()->lookup_type (stmt.get_mappings ().get_hirid (), + &ty)) + { + rust_fatal_error (stmt.get_locus (), "failed to lookup var decl type"); + return; + } + + // there is an ICE in GCC for void_node + if (ty->get_kind () == TyTy::TypeKind::UNIT) + return; + Bvariable *var = nullptr; if (!ctx->lookup_var_decl (stmt.get_mappings ().get_hirid (), &var)) { @@ -79,7 +91,8 @@ public: return; } - auto *init = CompileExpr::Compile (stmt.get_init_expr (), ctx); + Bexpression *init = CompileExpr::Compile (stmt.get_init_expr (), ctx); + auto fnctx = ctx->peek_fn (); auto s = ctx->get_backend ()->init_statement (fnctx.fndecl, var, init); ctx->add_statement (s); diff --git a/gcc/rust/backend/rust-compile-tyty.h b/gcc/rust/backend/rust-compile-tyty.h index 137b74b..cd220e0 100644 --- a/gcc/rust/backend/rust-compile-tyty.h +++ b/gcc/rust/backend/rust-compile-tyty.h @@ -45,8 +45,6 @@ public: void visit (TyTy::ErrorType &type) override { gcc_unreachable (); } - void visit (TyTy::UnitType &type) override { gcc_unreachable (); } - void visit (TyTy::InferType &type) override { gcc_unreachable (); } void visit (TyTy::StructFieldType &type) override { gcc_unreachable (); } @@ -57,6 +55,11 @@ public: void visit (TyTy::ArrayType &type) override { gcc_unreachable (); } + void visit (TyTy::UnitType &type) override + { + translated = backend->void_type (); + } + void visit (TyTy::FnType &type) override { Backend::Btyped_identifier receiver; -- cgit v1.1 From e4a2a52b35e99a40f8bd3992a6b53650908fd188 Mon Sep 17 00:00:00 2001 From: Philip Herron Date: Tue, 12 Jan 2021 17:12:00 +0000 Subject: Enforce type checking on implicit returns This change enforces strict type checkon on all ExprWithBlock. This includes unreachable tail expressions. Specific test cases have been added for context to ensure the failure cases are hit accordingly. This change also improves the diagnostic errors for mismatched types where the reference HirId was lost leading to default locations. --- gcc/rust/backend/rust-compile-context.h | 10 +++++----- gcc/rust/backend/rust-compile-item.h | 2 +- gcc/rust/backend/rust-compile.cc | 2 +- 3 files changed, 7 insertions(+), 7 deletions(-) (limited to 'gcc/rust/backend') diff --git a/gcc/rust/backend/rust-compile-context.h b/gcc/rust/backend/rust-compile-context.h index 5a0805b..fb227ac 100644 --- a/gcc/rust/backend/rust-compile-context.h +++ b/gcc/rust/backend/rust-compile-context.h @@ -239,7 +239,7 @@ public: void visit (TyTy::ADTType &type) override { ::Btype *compiled_type = nullptr; - bool ok = ctx->lookup_compiled_types (type.get_ref (), &compiled_type); + bool ok = ctx->lookup_compiled_types (type.get_ty_ref (), &compiled_type); rust_assert (ok); translated = compiled_type; } @@ -260,7 +260,7 @@ public: void visit (TyTy::BoolType &type) override { ::Btype *compiled_type = nullptr; - bool ok = ctx->lookup_compiled_types (type.get_ref (), &compiled_type); + bool ok = ctx->lookup_compiled_types (type.get_ty_ref (), &compiled_type); rust_assert (ok); translated = compiled_type; } @@ -268,7 +268,7 @@ public: void visit (TyTy::IntType &type) override { ::Btype *compiled_type = nullptr; - bool ok = ctx->lookup_compiled_types (type.get_ref (), &compiled_type); + bool ok = ctx->lookup_compiled_types (type.get_ty_ref (), &compiled_type); rust_assert (ok); translated = compiled_type; } @@ -276,7 +276,7 @@ public: void visit (TyTy::UintType &type) override { ::Btype *compiled_type = nullptr; - bool ok = ctx->lookup_compiled_types (type.get_ref (), &compiled_type); + bool ok = ctx->lookup_compiled_types (type.get_ty_ref (), &compiled_type); rust_assert (ok); translated = compiled_type; } @@ -284,7 +284,7 @@ public: void visit (TyTy::FloatType &type) override { ::Btype *compiled_type = nullptr; - bool ok = ctx->lookup_compiled_types (type.get_ref (), &compiled_type); + bool ok = ctx->lookup_compiled_types (type.get_ty_ref (), &compiled_type); rust_assert (ok); translated = compiled_type; } diff --git a/gcc/rust/backend/rust-compile-item.h b/gcc/rust/backend/rust-compile-item.h index c5fe9a2..8c7eda5 100644 --- a/gcc/rust/backend/rust-compile-item.h +++ b/gcc/rust/backend/rust-compile-item.h @@ -246,7 +246,7 @@ public: return true; }); - if (function_body->has_expr ()) + if (function_body->has_expr () && function_body->tail_expr_reachable ()) { // the previous passes will ensure this is a valid return // dead code elimination should remove any bad trailing expressions diff --git a/gcc/rust/backend/rust-compile.cc b/gcc/rust/backend/rust-compile.cc index 3f8a962..b394289 100644 --- a/gcc/rust/backend/rust-compile.cc +++ b/gcc/rust/backend/rust-compile.cc @@ -90,7 +90,7 @@ CompileBlock::visit (HIR::BlockExpr &expr) return true; }); - if (expr.has_expr ()) + if (expr.has_expr () && expr.tail_expr_reachable ()) { // the previous passes will ensure this is a valid return // dead code elimination should remove any bad trailing expressions -- cgit v1.1 From b06df5d4a95ec728ade9230bec945d5d3661f87d Mon Sep 17 00:00:00 2001 From: Philip Herron Date: Sat, 16 Jan 2021 17:25:12 +0000 Subject: This adds supports for tuples More testing is required but this adds tuples apart from TupleStructs which are parsed as CallExpr. This will be the primitives required to finish that work. --- gcc/rust/backend/rust-compile-context.h | 32 ++++++++++++++++++++++++++++---- gcc/rust/backend/rust-compile-expr.h | 24 +++++++++++++++++++++++- 2 files changed, 51 insertions(+), 5 deletions(-) (limited to 'gcc/rust/backend') diff --git a/gcc/rust/backend/rust-compile-context.h b/gcc/rust/backend/rust-compile-context.h index fb227ac..5288e51 100644 --- a/gcc/rust/backend/rust-compile-context.h +++ b/gcc/rust/backend/rust-compile-context.h @@ -238,10 +238,34 @@ public: void visit (TyTy::ADTType &type) override { - ::Btype *compiled_type = nullptr; - bool ok = ctx->lookup_compiled_types (type.get_ty_ref (), &compiled_type); - rust_assert (ok); - translated = compiled_type; + bool ok = ctx->lookup_compiled_types (type.get_ty_ref (), &translated); + if (ok) + return; + + // create implicit struct + std::vector fields; + for (size_t i = 0; i < type.num_fields (); i++) + { + TyTy::StructFieldType *field = type.get_field (i); + Btype *compiled_field_ty + = TyTyCompile::compile (ctx->get_backend (), + field->get_field_type ()); + + Backend::Btyped_identifier f (field->get_name (), compiled_field_ty, + ctx->get_mappings ()->lookup_location ( + type.get_ty_ref ())); + fields.push_back (std::move (f)); + } + + Btype *struct_type_record = ctx->get_backend ()->struct_type (fields); + Btype *named_struct + = ctx->get_backend ()->named_type (type.get_name (), struct_type_record, + ctx->get_mappings ()->lookup_location ( + type.get_ty_ref ())); + + ctx->push_type (named_struct); + ctx->insert_compiled_type (type.get_ty_ref (), named_struct); + translated = named_struct; } void visit (TyTy::ArrayType &type) override diff --git a/gcc/rust/backend/rust-compile-expr.h b/gcc/rust/backend/rust-compile-expr.h index d38ef04..0d3d9e8 100644 --- a/gcc/rust/backend/rust-compile-expr.h +++ b/gcc/rust/backend/rust-compile-expr.h @@ -46,7 +46,29 @@ public: return; } - gcc_unreachable (); + TyTy::TyBase *tyty = nullptr; + if (!ctx->get_tyctx ()->lookup_type (expr.get_mappings ().get_hirid (), + &tyty)) + { + rust_fatal_error (expr.get_locus (), + "did not resolve type for this TupleExpr"); + return; + } + + Btype *tuple_type = TyTyResolveCompile::compile (ctx, tyty); + rust_assert (tuple_type != nullptr); + + // this assumes all fields are in order from type resolution + std::vector vals; + for (auto &elem : expr.get_tuple_elems ()) + { + auto e = CompileExpr::Compile (elem.get (), ctx); + vals.push_back (e); + } + + translated + = ctx->get_backend ()->constructor_expression (tuple_type, vals, + expr.get_locus ()); } void visit (HIR::ReturnExpr &expr) -- cgit v1.1 From 7066c0eca18f99aca3e88a08b2aaf71d970d0ab6 Mon Sep 17 00:00:00 2001 From: Philip Herron Date: Sat, 16 Jan 2021 18:26:36 +0000 Subject: Support GroupedExpr's This makes the expression handling support exprs within parens. Such as: x = (2*a) + 3; --- gcc/rust/backend/rust-compile-expr.h | 5 +++++ 1 file changed, 5 insertions(+) (limited to 'gcc/rust/backend') diff --git a/gcc/rust/backend/rust-compile-expr.h b/gcc/rust/backend/rust-compile-expr.h index 0d3d9e8..682ff79 100644 --- a/gcc/rust/backend/rust-compile-expr.h +++ b/gcc/rust/backend/rust-compile-expr.h @@ -428,6 +428,11 @@ public: struct_expr.get_locus ()); } + void visit (HIR::GroupedExpr &expr) + { + translated = CompileExpr::Compile (expr.get_expr_in_parens ().get (), ctx); + } + private: CompileExpr (Context *ctx) : HIRCompileBase (ctx), translated (nullptr) {} -- cgit v1.1 From 659ade1611568da5d91a0d6a2d76871cce658ff7 Mon Sep 17 00:00:00 2001 From: Philip Herron Date: Sat, 16 Jan 2021 14:24:56 +0000 Subject: Handle forward references in backend compilation We must ensure the backend can support compilation of things declared lexically after they are referenced. This scans the toplevel except functions which are handled as we reference them. To make that generic enough for all toplevel items will be a move to query based compilation which still needs planning. --- gcc/rust/backend/rust-compile-item.h | 13 ++++++++++--- gcc/rust/backend/rust-compile.cc | 7 +++++-- 2 files changed, 15 insertions(+), 5 deletions(-) (limited to 'gcc/rust/backend') diff --git a/gcc/rust/backend/rust-compile-item.h b/gcc/rust/backend/rust-compile-item.h index 8c7eda5..a367ac7 100644 --- a/gcc/rust/backend/rust-compile-item.h +++ b/gcc/rust/backend/rust-compile-item.h @@ -31,9 +31,9 @@ namespace Compile { class CompileItem : public HIRCompileBase { public: - static void compile (HIR::Item *item, Context *ctx) + static void compile (HIR::Item *item, Context *ctx, bool compile_fns = true) { - CompileItem compiler (ctx); + CompileItem compiler (ctx, compile_fns); item->accept_vis (compiler); } @@ -116,6 +116,9 @@ public: void visit (HIR::Function &function) { + if (!compile_fns) + return; + // items can be forward compiled which means we may not need to invoke this // code Bfunction *lookup = nullptr; @@ -277,7 +280,11 @@ public: } private: - CompileItem (Context *ctx) : HIRCompileBase (ctx) {} + CompileItem (Context *ctx, bool compile_fns) + : HIRCompileBase (ctx), compile_fns (compile_fns) + {} + + bool compile_fns; }; } // namespace Compile diff --git a/gcc/rust/backend/rust-compile.cc b/gcc/rust/backend/rust-compile.cc index b394289..772d975 100644 --- a/gcc/rust/backend/rust-compile.cc +++ b/gcc/rust/backend/rust-compile.cc @@ -41,8 +41,11 @@ CompileCrate::Compile (HIR::Crate &crate, Context *ctx) void CompileCrate::go () { - for (auto it = crate.items.begin (); it != crate.items.end (); it++) - CompileItem::compile (it->get (), ctx); + for (auto &item : crate.items) + CompileItem::compile (item.get (), ctx, false); + + for (auto &item : crate.items) + CompileItem::compile (item.get (), ctx, true); } // rust-compile-block.h -- cgit v1.1 From 02132139efa60954c3f9d5aeb4d87210066b1b58 Mon Sep 17 00:00:00 2001 From: Philip Herron Date: Sat, 16 Jan 2021 14:34:06 +0000 Subject: Fix the naming of VAR_DECLS within gimple nodes. This was using LetStmt->Pattern.as_string which included mut in the string dump. This makes the gimple nodes harder to debug as the name is (mut a) insteaad of a for example. --- gcc/rust/backend/rust-compile-var-decl.h | 19 ++++++++++++++----- 1 file changed, 14 insertions(+), 5 deletions(-) (limited to 'gcc/rust/backend') diff --git a/gcc/rust/backend/rust-compile-var-decl.h b/gcc/rust/backend/rust-compile-var-decl.h index be3141a..cf73820 100644 --- a/gcc/rust/backend/rust-compile-var-decl.h +++ b/gcc/rust/backend/rust-compile-var-decl.h @@ -42,24 +42,33 @@ public: void visit (HIR::LetStmt &stmt) { + locus = stmt.get_locus (); TyTy::TyBase *resolved_type = nullptr; bool ok = ctx->get_tyctx ()->lookup_type (stmt.get_mappings ().get_hirid (), &resolved_type); rust_assert (ok); - ::Btype *translated_type = TyTyResolveCompile::compile (ctx, resolved_type); + translated_type = TyTyResolveCompile::compile (ctx, resolved_type); + stmt.get_pattern ()->accept_vis (*this); + } - translated = ctx->get_backend ()->local_variable ( - fndecl, stmt.get_pattern ()->as_string (), translated_type, - NULL /*decl_var*/, false /*address_taken*/, stmt.get_locus ()); + void visit (HIR::IdentifierPattern &pattern) + { + translated + = ctx->get_backend ()->local_variable (fndecl, pattern.variable_ident, + translated_type, NULL /*decl_var*/, + false /*address_taken*/, locus); } private: CompileVarDecl (Context *ctx, ::Bfunction *fndecl) - : HIRCompileBase (ctx), fndecl (fndecl), translated (nullptr) + : HIRCompileBase (ctx), fndecl (fndecl), translated_type (nullptr), + translated (nullptr) {} ::Bfunction *fndecl; + ::Btype *translated_type; + Location locus; ::Bvariable *translated; }; -- cgit v1.1 From 2b7518cf8ae5e34aec81dbb8efb6ea15bb95c68c Mon Sep 17 00:00:00 2001 From: Philip Herron Date: Sat, 16 Jan 2021 16:02:26 +0000 Subject: Add struct_field_expression support This adds in struct field expressions and should be generic enough for tuples later on. --- gcc/rust/backend/rust-compile-expr.h | 25 +++++++++++++++++++++++++ 1 file changed, 25 insertions(+) (limited to 'gcc/rust/backend') diff --git a/gcc/rust/backend/rust-compile-expr.h b/gcc/rust/backend/rust-compile-expr.h index 682ff79..98e8ee1 100644 --- a/gcc/rust/backend/rust-compile-expr.h +++ b/gcc/rust/backend/rust-compile-expr.h @@ -433,6 +433,31 @@ public: translated = CompileExpr::Compile (expr.get_expr_in_parens ().get (), ctx); } + void visit (HIR::FieldAccessExpr &expr) + { + // resolve the receiver back to ADT type + TyTy::TyBase *receiver = nullptr; + if (!ctx->get_tyctx ()->lookup_type ( + expr.get_receiver_expr ()->get_mappings ().get_hirid (), &receiver)) + { + rust_error_at (expr.get_receiver_expr ()->get_locus_slow (), + "unresolved type for receiver"); + return; + } + rust_assert (receiver->get_kind () == TyTy::TypeKind::ADT); + + TyTy::ADTType *adt = (TyTy::ADTType *) receiver; + size_t index = 0; + adt->get_field (expr.get_field_name (), &index); + + Bexpression *struct_ref + = CompileExpr::Compile (expr.get_receiver_expr ().get (), ctx); + + translated + = ctx->get_backend ()->struct_field_expression (struct_ref, index, + expr.get_locus ()); + } + private: CompileExpr (Context *ctx) : HIRCompileBase (ctx), translated (nullptr) {} -- cgit v1.1 From 9a942d6fbd0cc087cbc801ce4681a498e59dce2c Mon Sep 17 00:00:00 2001 From: Philip Herron Date: Mon, 18 Jan 2021 14:51:36 +0000 Subject: Add in TupleStruct support This adds in tuple struct support with name and type resolution. The arguments and number of arguments are validated against. Test cases added for those errors too. --- gcc/rust/backend/rust-compile-expr.h | 19 +---------- gcc/rust/backend/rust-compile-item.h | 47 +++++++++++++-------------- gcc/rust/backend/rust-compile-resolve-path.cc | 12 +++---- gcc/rust/backend/rust-compile-resolve-path.h | 2 -- gcc/rust/backend/rust-compile.cc | 47 +++++++++++++++++++++++++++ 5 files changed, 75 insertions(+), 52 deletions(-) (limited to 'gcc/rust/backend') diff --git a/gcc/rust/backend/rust-compile-expr.h b/gcc/rust/backend/rust-compile-expr.h index 98e8ee1..8b99574 100644 --- a/gcc/rust/backend/rust-compile-expr.h +++ b/gcc/rust/backend/rust-compile-expr.h @@ -86,24 +86,7 @@ public: ctx->add_statement (s); } - void visit (HIR::CallExpr &expr) - { - Bexpression *fn = ResolvePathRef::Compile (expr.get_fnexpr (), ctx); - rust_assert (fn != nullptr); - - std::vector args; - expr.iterate_params ([&] (HIR::Expr *p) mutable -> bool { - Bexpression *compiled_expr = CompileExpr::Compile (p, ctx); - rust_assert (compiled_expr != nullptr); - args.push_back (compiled_expr); - return true; - }); - - auto fncontext = ctx->peek_fn (); - translated - = ctx->get_backend ()->call_expression (fncontext.fndecl, fn, args, - nullptr, expr.get_locus ()); - } + void visit (HIR::CallExpr &expr); void visit (HIR::IdentifierExpr &expr) { diff --git a/gcc/rust/backend/rust-compile-item.h b/gcc/rust/backend/rust-compile-item.h index a367ac7..c8cffc7 100644 --- a/gcc/rust/backend/rust-compile-item.h +++ b/gcc/rust/backend/rust-compile-item.h @@ -37,35 +37,32 @@ public: item->accept_vis (compiler); } - virtual ~CompileItem () {} - - void visit (HIR::StructStruct &struct_decl) + void visit (HIR::TupleStruct &struct_decl) { - std::vector fields; - struct_decl.iterate ([&] (HIR::StructField &field) mutable -> bool { - TyTy::TyBase *resolved_type = nullptr; - bool ok - = ctx->get_tyctx ()->lookup_type (field.get_mappings ().get_hirid (), - &resolved_type); - rust_assert (ok); + TyTy::TyBase *resolved = nullptr; + if (!ctx->get_tyctx ()->lookup_type ( + struct_decl.get_mappings ().get_hirid (), &resolved)) + { + rust_fatal_error (struct_decl.get_locus (), + "Failed to lookup type for struct decl"); + return; + } - Btype *compiled_field_ty - = TyTyCompile::compile (ctx->get_backend (), resolved_type); + TyTyResolveCompile::compile (ctx, resolved); + } - Backend::Btyped_identifier f (field.field_name, compiled_field_ty, - field.get_locus ()); - fields.push_back (std::move (f)); - return true; - }); + void visit (HIR::StructStruct &struct_decl) + { + TyTy::TyBase *resolved = nullptr; + if (!ctx->get_tyctx ()->lookup_type ( + struct_decl.get_mappings ().get_hirid (), &resolved)) + { + rust_fatal_error (struct_decl.get_locus (), + "Failed to lookup type for struct decl"); + return; + } - Btype *struct_type_record = ctx->get_backend ()->struct_type (fields); - Btype *named_struct - = ctx->get_backend ()->named_type (struct_decl.get_identifier (), - struct_type_record, - struct_decl.get_locus ()); - ctx->push_type (named_struct); - ctx->insert_compiled_type (struct_decl.get_mappings ().get_hirid (), - named_struct); + TyTyResolveCompile::compile (ctx, resolved); } void visit (HIR::StaticItem &var) diff --git a/gcc/rust/backend/rust-compile-resolve-path.cc b/gcc/rust/backend/rust-compile-resolve-path.cc index 374f8a0..37285b7 100644 --- a/gcc/rust/backend/rust-compile-resolve-path.cc +++ b/gcc/rust/backend/rust-compile-resolve-path.cc @@ -32,7 +32,6 @@ ResolvePathRef::visit (HIR::PathInExpression &expr) if (!ctx->get_resolver ()->lookup_resolved_name ( expr.get_mappings ().get_nodeid (), &ref_node_id)) { - rust_fatal_error (expr.get_locus (), "failed to look up resolved name"); return; } @@ -40,7 +39,7 @@ ResolvePathRef::visit (HIR::PathInExpression &expr) if (!ctx->get_mappings ()->lookup_node_to_hir ( expr.get_mappings ().get_crate_num (), ref_node_id, &ref)) { - rust_fatal_error (expr.get_locus (), "reverse lookup failure"); + rust_error_at (expr.get_locus (), "reverse lookup failure"); return; } @@ -54,14 +53,14 @@ ResolvePathRef::visit (HIR::PathInExpression &expr) expr.get_mappings ().get_crate_num (), ref); if (resolved_item == nullptr) { - rust_fatal_error (expr.get_locus (), "failed to lookup forward decl"); + rust_error_at (expr.get_locus (), "failed to lookup forward decl"); return; } CompileItem::compile (resolved_item, ctx); if (!ctx->lookup_function_decl (ref, &fn)) { - rust_fatal_error (expr.get_locus (), "forward decl was not compiled"); + rust_error_at (expr.get_locus (), "forward decl was not compiled"); return; } } @@ -78,7 +77,6 @@ ResolvePathType::visit (HIR::PathInExpression &expr) if (!ctx->get_resolver ()->lookup_resolved_type ( expr.get_mappings ().get_nodeid (), &ref_node_id)) { - rust_fatal_error (expr.get_locus (), "failed to look up resolved name"); return; } @@ -86,14 +84,14 @@ ResolvePathType::visit (HIR::PathInExpression &expr) if (!ctx->get_mappings ()->lookup_node_to_hir ( expr.get_mappings ().get_crate_num (), ref_node_id, &ref)) { - rust_fatal_error (expr.get_locus (), "reverse lookup failure"); + rust_error_at (expr.get_locus (), "reverse lookup failure"); return; } // assumes paths are functions for now if (!ctx->lookup_compiled_types (ref, &resolved)) { - rust_fatal_error (expr.get_locus (), "forward decl was not compiled"); + rust_error_at (expr.get_locus (), "forward decl was not compiled"); return; } } diff --git a/gcc/rust/backend/rust-compile-resolve-path.h b/gcc/rust/backend/rust-compile-resolve-path.h index a5543d2..2f3cb68 100644 --- a/gcc/rust/backend/rust-compile-resolve-path.h +++ b/gcc/rust/backend/rust-compile-resolve-path.h @@ -32,7 +32,6 @@ public: { ResolvePathRef resolver (ctx); expr->accept_vis (resolver); - rust_assert (resolver.resolved != nullptr); return resolver.resolved; } @@ -51,7 +50,6 @@ public: { ResolvePathType resolver (ctx); expr->accept_vis (resolver); - rust_assert (resolver.resolved != nullptr); return resolver.resolved; } diff --git a/gcc/rust/backend/rust-compile.cc b/gcc/rust/backend/rust-compile.cc index 772d975..6519a47 100644 --- a/gcc/rust/backend/rust-compile.cc +++ b/gcc/rust/backend/rust-compile.cc @@ -48,6 +48,53 @@ CompileCrate::go () CompileItem::compile (item.get (), ctx, true); } +// rust-compile-expr.h + +void +CompileExpr::visit (HIR::CallExpr &expr) +{ + // this can be a function call or it can be a constructor for a tuple struct + Bexpression *fn = ResolvePathRef::Compile (expr.get_fnexpr (), ctx); + if (fn != nullptr) + { + std::vector args; + expr.iterate_params ([&] (HIR::Expr *p) mutable -> bool { + Bexpression *compiled_expr = CompileExpr::Compile (p, ctx); + rust_assert (compiled_expr != nullptr); + args.push_back (compiled_expr); + return true; + }); + + auto fncontext = ctx->peek_fn (); + translated + = ctx->get_backend ()->call_expression (fncontext.fndecl, fn, args, + nullptr, expr.get_locus ()); + } + else + { + Btype *type = ResolvePathType::Compile (expr.get_fnexpr (), ctx); + if (type == nullptr) + { + rust_fatal_error (expr.get_locus (), + "failed to lookup type associated with call"); + return; + } + + // this assumes all fields are in order from type resolution and if a base + // struct was specified those fields are filed via accesors + std::vector vals; + expr.iterate_params ([&] (HIR::Expr *argument) mutable -> bool { + Bexpression *e = CompileExpr::Compile (argument, ctx); + vals.push_back (e); + return true; + }); + + translated + = ctx->get_backend ()->constructor_expression (type, vals, + expr.get_locus ()); + } +} + // rust-compile-block.h void -- cgit v1.1 From f8d41b7e8a3a65382dc5ce30dfb3f85abe298d19 Mon Sep 17 00:00:00 2001 From: Philip Herron Date: Mon, 18 Jan 2021 15:51:35 +0000 Subject: Add TupleIndexExpressions Now we can type resolve and reference the results from TupleIndexExpr's. --- gcc/rust/backend/rust-compile-expr.h | 11 +++++++++++ 1 file changed, 11 insertions(+) (limited to 'gcc/rust/backend') diff --git a/gcc/rust/backend/rust-compile-expr.h b/gcc/rust/backend/rust-compile-expr.h index 8b99574..ff02d6b 100644 --- a/gcc/rust/backend/rust-compile-expr.h +++ b/gcc/rust/backend/rust-compile-expr.h @@ -38,6 +38,17 @@ public: return compiler.translated; } + void visit (HIR::TupleIndexExpr &expr) + { + HIR::Expr *tuple_expr = expr.get_tuple_expr ().get (); + TupleIndex index = expr.get_tuple_index (); + + Bexpression *receiver_ref = CompileExpr::Compile (tuple_expr, ctx); + translated + = ctx->get_backend ()->struct_field_expression (receiver_ref, index, + expr.get_locus ()); + } + void visit (HIR::TupleExpr &expr) { if (expr.is_unit ()) -- cgit v1.1 From 6e2acd529fcfa43368f7ea8209cc5e6b88d2bd79 Mon Sep 17 00:00:00 2001 From: Philip Herron Date: Mon, 18 Jan 2021 16:47:16 +0000 Subject: Support Struct field index initialisation For TupleStructs the constructor can take field indexes to support change or ordering of the fields. --- gcc/rust/backend/rust-compile-struct-field-expr.h | 2 ++ gcc/rust/backend/rust-compile.cc | 6 ++++++ 2 files changed, 8 insertions(+) (limited to 'gcc/rust/backend') diff --git a/gcc/rust/backend/rust-compile-struct-field-expr.h b/gcc/rust/backend/rust-compile-struct-field-expr.h index a394f7a..0e54281 100644 --- a/gcc/rust/backend/rust-compile-struct-field-expr.h +++ b/gcc/rust/backend/rust-compile-struct-field-expr.h @@ -38,6 +38,8 @@ public: void visit (HIR::StructExprFieldIdentifierValue &field); + void visit (HIR::StructExprFieldIndexValue &field); + private: CompileStructExprField (Context *ctx) : HIRCompileBase (ctx), translated (nullptr) diff --git a/gcc/rust/backend/rust-compile.cc b/gcc/rust/backend/rust-compile.cc index 6519a47..cb6272f 100644 --- a/gcc/rust/backend/rust-compile.cc +++ b/gcc/rust/backend/rust-compile.cc @@ -228,5 +228,11 @@ CompileStructExprField::visit (HIR::StructExprFieldIdentifierValue &field) translated = CompileExpr::Compile (field.get_value (), ctx); } +void +CompileStructExprField::visit (HIR::StructExprFieldIndexValue &field) +{ + translated = CompileExpr::Compile (field.get_value (), ctx); +} + } // namespace Compile } // namespace Rust -- cgit v1.1 From 12f7bd0fc4e9ab4e98869b5265aea6bacfb31d03 Mon Sep 17 00:00:00 2001 From: Philip Herron Date: Mon, 18 Jan 2021 17:57:22 +0000 Subject: Support struct initializers using Identifiers This resolves each identifier for its respective field. It includes fixes for the TypeResolver to print errors instead of asserts where we loose decent debug info. --- gcc/rust/backend/rust-compile-struct-field-expr.h | 2 ++ gcc/rust/backend/rust-compile.cc | 10 ++++++++++ 2 files changed, 12 insertions(+) (limited to 'gcc/rust/backend') diff --git a/gcc/rust/backend/rust-compile-struct-field-expr.h b/gcc/rust/backend/rust-compile-struct-field-expr.h index 0e54281..0a16f6a 100644 --- a/gcc/rust/backend/rust-compile-struct-field-expr.h +++ b/gcc/rust/backend/rust-compile-struct-field-expr.h @@ -40,6 +40,8 @@ public: void visit (HIR::StructExprFieldIndexValue &field); + void visit (HIR::StructExprFieldIdentifier &field); + private: CompileStructExprField (Context *ctx) : HIRCompileBase (ctx), translated (nullptr) diff --git a/gcc/rust/backend/rust-compile.cc b/gcc/rust/backend/rust-compile.cc index cb6272f..ce6d827 100644 --- a/gcc/rust/backend/rust-compile.cc +++ b/gcc/rust/backend/rust-compile.cc @@ -234,5 +234,15 @@ CompileStructExprField::visit (HIR::StructExprFieldIndexValue &field) translated = CompileExpr::Compile (field.get_value (), ctx); } +void +CompileStructExprField::visit (HIR::StructExprFieldIdentifier &field) +{ + // we can make the field look like an identifier expr to take advantage of + // existing code + HIR::IdentifierExpr expr (field.get_mappings (), field.get_field_name (), + field.get_locus ()); + translated = CompileExpr::Compile (&expr, ctx); +} + } // namespace Compile } // namespace Rust -- cgit v1.1 From f6d33adc6656839aebb4dca02df8efc8be6aedd2 Mon Sep 17 00:00:00 2001 From: Philip Herron Date: Tue, 19 Jan 2021 12:03:01 +0000 Subject: Fix bug using ADT types as return types to functions When we use anything other than builtin types for returns or parameters the type resolver was missing the NodeId mappings meaning it would alawys fail to resolve them. Then in gimple conversion we need to be able to reference the already created RECORD types instead of always creating new instances. --- gcc/rust/backend/rust-compile-context.h | 80 ++++++++++++++++++++++++++++++++- gcc/rust/backend/rust-compile-item.h | 15 +++---- gcc/rust/backend/rust-compile-tyty.h | 48 -------------------- 3 files changed, 85 insertions(+), 58 deletions(-) (limited to 'gcc/rust/backend') diff --git a/gcc/rust/backend/rust-compile-context.h b/gcc/rust/backend/rust-compile-context.h index 5288e51..6516c71 100644 --- a/gcc/rust/backend/rust-compile-context.h +++ b/gcc/rust/backend/rust-compile-context.h @@ -225,12 +225,43 @@ public: void visit (TyTy::InferType &type) override { gcc_unreachable (); } - void visit (TyTy::FnType &type) override { gcc_unreachable (); } - void visit (TyTy::StructFieldType &type) override { gcc_unreachable (); } void visit (TyTy::ParamType &type) override { gcc_unreachable (); } + void visit (TyTy::FnType &type) override + { + Backend::Btyped_identifier receiver; + std::vector parameters; + std::vector results; + + if (!type.get_return_type ()->is_unit ()) + { + auto hir_type = type.get_return_type (); + auto ret = TyTyResolveCompile::compile (ctx, hir_type); + results.push_back (Backend::Btyped_identifier ( + "_", ret, + ctx->get_mappings ()->lookup_location (hir_type->get_ref ()))); + } + + for (size_t i = 0; i < type.num_params (); i++) + { + auto param_tyty = type.param_at (i); + auto compiled_param_type + = TyTyResolveCompile::compile (ctx, param_tyty->get_base_type ()); + + auto compiled_param = Backend::Btyped_identifier ( + param_tyty->get_identifier (), compiled_param_type, + ctx->get_mappings ()->lookup_location (param_tyty->get_ref ())); + + parameters.push_back (compiled_param); + } + + translated = ctx->get_backend ()->function_type ( + receiver, parameters, results, NULL, + ctx->get_mappings ()->lookup_location (type.get_ref ())); + } + void visit (TyTy::UnitType &type) override { translated = ctx->get_backend ()->void_type (); @@ -320,6 +351,51 @@ private: ::Btype *translated; }; +class TyTyCompileParam : public TyTy::TyVisitor +{ +public: + static ::Bvariable *compile (Context *ctx, Bfunction *fndecl, + TyTy::TyBase *ty) + { + TyTyCompileParam compiler (ctx, fndecl); + ty->accept_vis (compiler); + rust_assert (compiler.translated != nullptr); + return compiler.translated; + } + + ~TyTyCompileParam () {} + + void visit (TyTy::UnitType &type) override { gcc_unreachable (); } + void visit (TyTy::InferType &type) override { gcc_unreachable (); } + void visit (TyTy::StructFieldType &type) override { gcc_unreachable (); } + void visit (TyTy::ADTType &type) override { gcc_unreachable (); } + void visit (TyTy::FnType &type) override { gcc_unreachable (); } + void visit (TyTy::ArrayType &type) override { gcc_unreachable (); } + void visit (TyTy::BoolType &type) override { gcc_unreachable (); } + void visit (TyTy::IntType &type) override { gcc_unreachable (); } + void visit (TyTy::UintType &type) override { gcc_unreachable (); } + void visit (TyTy::FloatType &type) override { gcc_unreachable (); } + void visit (TyTy::ErrorType &type) override { gcc_unreachable (); } + + void visit (TyTy::ParamType &type) override + { + auto btype = TyTyResolveCompile::compile (ctx, type.get_base_type ()); + bool tree_addressable = false; + translated = ctx->get_backend ()->parameter_variable ( + fndecl, type.get_identifier (), btype, tree_addressable, + ctx->get_mappings ()->lookup_location (type.get_ref ())); + } + +private: + TyTyCompileParam (Context *ctx, ::Bfunction *fndecl) + : ctx (ctx), fndecl (fndecl), translated (nullptr) + {} + + Context *ctx; + ::Bfunction *fndecl; + ::Bvariable *translated; +}; + } // namespace Compile } // namespace Rust diff --git a/gcc/rust/backend/rust-compile-item.h b/gcc/rust/backend/rust-compile-item.h index c8cffc7..82dbc9b 100644 --- a/gcc/rust/backend/rust-compile-item.h +++ b/gcc/rust/backend/rust-compile-item.h @@ -127,16 +127,16 @@ public: return; } - TyTy::TyBase *fnType; + TyTy::TyBase *fntype; if (!ctx->get_tyctx ()->lookup_type (function.get_mappings ().get_hirid (), - &fnType)) + &fntype)) { rust_fatal_error (function.locus, "failed to lookup function type"); return; } // convert to the actual function type - auto compiled_fn_type = TyTyCompile::compile (ctx->get_backend (), fnType); + ::Btype *compiled_fn_type = TyTyResolveCompile::compile (ctx, fntype); unsigned int flags = 0; bool is_main_fn = function.function_name.compare ("main") == 0; @@ -159,15 +159,14 @@ public: ctx->insert_function_decl (function.get_mappings ().get_hirid (), fndecl); // setup the params - TyTy::TyBase *tyret = TyTyExtractRetFromFnType::compile (fnType); + TyTy::TyBase *tyret = TyTyExtractRetFromFnType::compile (fntype); std::vector typarams - = TyTyExtractParamsFromFnType::compile (fnType); + = TyTyExtractParamsFromFnType::compile (fntype); std::vector param_vars; for (auto &it : typarams) { - auto compiled_param - = TyTyCompileParam::compile (ctx->get_backend (), fndecl, it); + auto compiled_param = TyTyCompileParam::compile (ctx, fndecl, it); param_vars.push_back (compiled_param); ctx->insert_var_decl (it->get_ref (), compiled_param); @@ -226,7 +225,7 @@ public: Bvariable *return_address = nullptr; if (function.has_function_return_type ()) { - Btype *return_type = TyTyCompile::compile (ctx->get_backend (), tyret); + Btype *return_type = TyTyResolveCompile::compile (ctx, tyret); bool address_is_taken = false; Bstatement *ret_var_stmt = nullptr; diff --git a/gcc/rust/backend/rust-compile-tyty.h b/gcc/rust/backend/rust-compile-tyty.h index cd220e0..3eb2ca5 100644 --- a/gcc/rust/backend/rust-compile-tyty.h +++ b/gcc/rust/backend/rust-compile-tyty.h @@ -278,54 +278,6 @@ private: TyTy::TyBase *translated; }; -class TyTyCompileParam : public TyTy::TyVisitor -{ -public: - static ::Bvariable *compile (::Backend *backend, Bfunction *fndecl, - TyTy::TyBase *ty) - { - TyTyCompileParam compiler (backend, fndecl); - ty->accept_vis (compiler); - rust_assert (compiler.translated != nullptr); - return compiler.translated; - } - - ~TyTyCompileParam () {} - - void visit (TyTy::UnitType &type) override { gcc_unreachable (); } - void visit (TyTy::InferType &type) override { gcc_unreachable (); } - void visit (TyTy::StructFieldType &type) override { gcc_unreachable (); } - void visit (TyTy::ADTType &type) override { gcc_unreachable (); } - void visit (TyTy::FnType &type) override { gcc_unreachable (); } - void visit (TyTy::ArrayType &type) override { gcc_unreachable (); } - void visit (TyTy::BoolType &type) override { gcc_unreachable (); } - void visit (TyTy::IntType &type) override { gcc_unreachable (); } - void visit (TyTy::UintType &type) override { gcc_unreachable (); } - void visit (TyTy::FloatType &type) override { gcc_unreachable (); } - void visit (TyTy::ErrorType &type) override { gcc_unreachable (); } - - void visit (TyTy::ParamType &type) override - { - auto btype = TyTyCompile::compile (backend, type.get_base_type ()); - bool tree_addressable = false; - translated = backend->parameter_variable (fndecl, type.get_identifier (), - btype, tree_addressable, - mappings->lookup_location ( - type.get_ref ())); - } - -private: - TyTyCompileParam (::Backend *backend, ::Bfunction *fndecl) - : backend (backend), translated (nullptr), fndecl (fndecl), - mappings (Analysis::Mappings::get ()) - {} - - ::Backend *backend; - ::Bvariable *translated; - ::Bfunction *fndecl; - Analysis::Mappings *mappings; -}; - } // namespace Compile } // namespace Rust -- cgit v1.1 From 85d8754632d597fe3d94404406082bcbb2f5ff94 Mon Sep 17 00:00:00 2001 From: Philip Herron Date: Tue, 19 Jan 2021 17:02:45 +0000 Subject: Implement NegationExpression This is an example of a unary expression in gimple. The rules for enforcing the types are observed in the type resolver here too. Unary negate cannot be applied to bools but only integers and floats. Unary not cannot be applied to floating points but can be applied to integers and bools. --- gcc/rust/backend/rust-compile-expr.h | 19 +++++++++++++++++++ 1 file changed, 19 insertions(+) (limited to 'gcc/rust/backend') diff --git a/gcc/rust/backend/rust-compile-expr.h b/gcc/rust/backend/rust-compile-expr.h index ff02d6b..da3c9cd 100644 --- a/gcc/rust/backend/rust-compile-expr.h +++ b/gcc/rust/backend/rust-compile-expr.h @@ -378,6 +378,25 @@ public: expr.get_locus ()); } + void visit (HIR::NegationExpr &expr) + { + Operator op (OPERATOR_INVALID); + switch (expr.get_negation_type ()) + { + case HIR::NegationExpr::NegationType::NEGATE: + op = OPERATOR_MINUS; + break; + + case HIR::NegationExpr::NegationType::NOT: + op = OPERATOR_NOT; + break; + } + + Bexpression *negated_expr = CompileExpr::Compile (expr.get_expr (), ctx); + translated = ctx->get_backend ()->unary_expression (op, negated_expr, + expr.get_locus ()); + } + void visit (HIR::IfExpr &expr) { auto stmt = CompileConditionalBlocks::compile (&expr, ctx); -- cgit v1.1 From 5294dfe7dce7a58fbaf2131c7589d115008ebf0e Mon Sep 17 00:00:00 2001 From: Philip Herron Date: Thu, 21 Jan 2021 17:04:14 +0000 Subject: Remove TyTy::ParamType this was wrongly used to represent FunctionParams TyTy::ParamType is meant to be used to represent Generic Types which is not handled yet as part of this current milestone. --- gcc/rust/backend/rust-compile-context.h | 56 ++------------------ gcc/rust/backend/rust-compile-item.h | 39 ++++++++++---- gcc/rust/backend/rust-compile-tyty.h | 93 +++------------------------------ 3 files changed, 42 insertions(+), 146 deletions(-) (limited to 'gcc/rust/backend') diff --git a/gcc/rust/backend/rust-compile-context.h b/gcc/rust/backend/rust-compile-context.h index 6516c71..df29e36 100644 --- a/gcc/rust/backend/rust-compile-context.h +++ b/gcc/rust/backend/rust-compile-context.h @@ -26,6 +26,7 @@ #include "rust-backend.h" #include "rust-compile-tyty.h" #include "rust-ast-full.h" +#include "rust-hir-full.h" namespace Rust { namespace Compile { @@ -227,8 +228,6 @@ public: void visit (TyTy::StructFieldType &type) override { gcc_unreachable (); } - void visit (TyTy::ParamType &type) override { gcc_unreachable (); } - void visit (TyTy::FnType &type) override { Backend::Btyped_identifier receiver; @@ -244,14 +243,14 @@ public: ctx->get_mappings ()->lookup_location (hir_type->get_ref ()))); } - for (size_t i = 0; i < type.num_params (); i++) + for (auto ¶m_pair : type.get_params ()) { - auto param_tyty = type.param_at (i); + auto param_tyty = param_pair.second; auto compiled_param_type - = TyTyResolveCompile::compile (ctx, param_tyty->get_base_type ()); + = TyTyResolveCompile::compile (ctx, param_tyty); auto compiled_param = Backend::Btyped_identifier ( - param_tyty->get_identifier (), compiled_param_type, + param_pair.first->as_string (), compiled_param_type, ctx->get_mappings ()->lookup_location (param_tyty->get_ref ())); parameters.push_back (compiled_param); @@ -351,51 +350,6 @@ private: ::Btype *translated; }; -class TyTyCompileParam : public TyTy::TyVisitor -{ -public: - static ::Bvariable *compile (Context *ctx, Bfunction *fndecl, - TyTy::TyBase *ty) - { - TyTyCompileParam compiler (ctx, fndecl); - ty->accept_vis (compiler); - rust_assert (compiler.translated != nullptr); - return compiler.translated; - } - - ~TyTyCompileParam () {} - - void visit (TyTy::UnitType &type) override { gcc_unreachable (); } - void visit (TyTy::InferType &type) override { gcc_unreachable (); } - void visit (TyTy::StructFieldType &type) override { gcc_unreachable (); } - void visit (TyTy::ADTType &type) override { gcc_unreachable (); } - void visit (TyTy::FnType &type) override { gcc_unreachable (); } - void visit (TyTy::ArrayType &type) override { gcc_unreachable (); } - void visit (TyTy::BoolType &type) override { gcc_unreachable (); } - void visit (TyTy::IntType &type) override { gcc_unreachable (); } - void visit (TyTy::UintType &type) override { gcc_unreachable (); } - void visit (TyTy::FloatType &type) override { gcc_unreachable (); } - void visit (TyTy::ErrorType &type) override { gcc_unreachable (); } - - void visit (TyTy::ParamType &type) override - { - auto btype = TyTyResolveCompile::compile (ctx, type.get_base_type ()); - bool tree_addressable = false; - translated = ctx->get_backend ()->parameter_variable ( - fndecl, type.get_identifier (), btype, tree_addressable, - ctx->get_mappings ()->lookup_location (type.get_ref ())); - } - -private: - TyTyCompileParam (Context *ctx, ::Bfunction *fndecl) - : ctx (ctx), fndecl (fndecl), translated (nullptr) - {} - - Context *ctx; - ::Bfunction *fndecl; - ::Bvariable *translated; -}; - } // namespace Compile } // namespace Rust diff --git a/gcc/rust/backend/rust-compile-item.h b/gcc/rust/backend/rust-compile-item.h index 82dbc9b..bf899d8 100644 --- a/gcc/rust/backend/rust-compile-item.h +++ b/gcc/rust/backend/rust-compile-item.h @@ -127,14 +127,21 @@ public: return; } - TyTy::TyBase *fntype; + TyTy::TyBase *fntype_tyty; if (!ctx->get_tyctx ()->lookup_type (function.get_mappings ().get_hirid (), - &fntype)) + &fntype_tyty)) { rust_fatal_error (function.locus, "failed to lookup function type"); return; } + if (fntype_tyty->get_kind () != TyTy::TypeKind::FNDEF) + { + rust_error_at (function.get_locus (), "invalid TyTy for function item"); + return; + } + + TyTy::FnType *fntype = (TyTy::FnType *) fntype_tyty; // convert to the actual function type ::Btype *compiled_fn_type = TyTyResolveCompile::compile (ctx, fntype); @@ -159,17 +166,31 @@ public: ctx->insert_function_decl (function.get_mappings ().get_hirid (), fndecl); // setup the params - TyTy::TyBase *tyret = TyTyExtractRetFromFnType::compile (fntype); - std::vector typarams - = TyTyExtractParamsFromFnType::compile (fntype); + + TyTy::TyBase *tyret = fntype->return_type (); std::vector param_vars; - for (auto &it : typarams) + size_t i = 0; + for (auto &it : fntype->get_params ()) { - auto compiled_param = TyTyCompileParam::compile (ctx, fndecl, it); - param_vars.push_back (compiled_param); + HIR::FunctionParam &referenced_param = function.function_params.at (i); + auto param_pattern = it.first; + auto param_tyty = it.second; + + auto compiled_param_type + = TyTyResolveCompile::compile (ctx, param_tyty); + + bool tree_addressable = false; + auto compiled_param_var = ctx->get_backend ()->parameter_variable ( + fndecl, param_pattern->as_string (), compiled_param_type, + tree_addressable, + ctx->get_mappings ()->lookup_location (param_tyty->get_ref ())); + + param_vars.push_back (compiled_param_var); - ctx->insert_var_decl (it->get_ref (), compiled_param); + ctx->insert_var_decl (referenced_param.get_mappings ().get_hirid (), + compiled_param_var); + i++; } if (!ctx->get_backend ()->function_set_parameters (fndecl, param_vars)) diff --git a/gcc/rust/backend/rust-compile-tyty.h b/gcc/rust/backend/rust-compile-tyty.h index 3eb2ca5..f74b4ac 100644 --- a/gcc/rust/backend/rust-compile-tyty.h +++ b/gcc/rust/backend/rust-compile-tyty.h @@ -26,6 +26,7 @@ #include "rust-tyty.h" #include "rust-tyty-visitor.h" #include "rust-hir-map.h" +#include "rust-hir-full.h" namespace Rust { namespace Compile { @@ -49,8 +50,6 @@ public: void visit (TyTy::StructFieldType &type) override { gcc_unreachable (); } - void visit (TyTy::ParamType &type) override { gcc_unreachable (); } - void visit (TyTy::ADTType &type) override { gcc_unreachable (); } void visit (TyTy::ArrayType &type) override { gcc_unreachable (); } @@ -74,13 +73,14 @@ public: "_", ret, mappings->lookup_location (hir_type->get_ref ()))); } - for (size_t i = 0; i < type.num_params (); i++) + for (auto ¶ms : type.get_params ()) { - auto param_tyty = type.param_at (i); - auto compiled_param_type - = TyTyCompile::compile (backend, param_tyty->get_base_type ()); + auto param_pattern = params.first; + auto param_tyty = params.second; + auto compiled_param_type = TyTyCompile::compile (backend, param_tyty); + auto compiled_param = Backend::Btyped_identifier ( - param_tyty->get_identifier (), compiled_param_type, + param_pattern->as_string (), compiled_param_type, mappings->lookup_location (param_tyty->get_ref ())); parameters.push_back (compiled_param); @@ -199,85 +199,6 @@ private: Analysis::Mappings *mappings; }; -class TyTyExtractParamsFromFnType : public TyTy::TyVisitor -{ -public: - static std::vector compile (TyTy::TyBase *ty) - { - TyTyExtractParamsFromFnType compiler; - ty->accept_vis (compiler); - rust_assert (compiler.ok); - return compiler.translated; - } - - ~TyTyExtractParamsFromFnType () {} - - void visit (TyTy::UnitType &type) override { gcc_unreachable (); } - void visit (TyTy::InferType &type) override { gcc_unreachable (); } - void visit (TyTy::StructFieldType &type) override { gcc_unreachable (); } - void visit (TyTy::ADTType &type) override { gcc_unreachable (); } - void visit (TyTy::ParamType &type) override { gcc_unreachable (); } - void visit (TyTy::ArrayType &type) override { gcc_unreachable (); } - void visit (TyTy::BoolType &type) override { gcc_unreachable (); } - void visit (TyTy::IntType &type) override { gcc_unreachable (); } - void visit (TyTy::UintType &type) override { gcc_unreachable (); } - void visit (TyTy::FloatType &type) override { gcc_unreachable (); } - void visit (TyTy::ErrorType &type) override { gcc_unreachable (); } - - void visit (TyTy::FnType &type) override - { - ok = true; - for (size_t i = 0; i < type.num_params (); i++) - { - translated.push_back (type.param_at (i)); - } - } - -private: - TyTyExtractParamsFromFnType () : ok (false) {} - - bool ok; - std::vector translated; -}; - -class TyTyExtractRetFromFnType : public TyTy::TyVisitor -{ -public: - static TyTy::TyBase *compile (TyTy::TyBase *ty) - { - TyTyExtractRetFromFnType compiler; - ty->accept_vis (compiler); - rust_assert (compiler.ok); - return compiler.translated; - } - - ~TyTyExtractRetFromFnType () {} - - void visit (TyTy::UnitType &type) override { gcc_unreachable (); } - void visit (TyTy::InferType &type) override { gcc_unreachable (); } - void visit (TyTy::StructFieldType &type) override { gcc_unreachable (); } - void visit (TyTy::ADTType &type) override { gcc_unreachable (); } - void visit (TyTy::ParamType &type) override { gcc_unreachable (); } - void visit (TyTy::ArrayType &type) override { gcc_unreachable (); } - void visit (TyTy::BoolType &type) override { gcc_unreachable (); } - void visit (TyTy::IntType &type) override { gcc_unreachable (); } - void visit (TyTy::UintType &type) override { gcc_unreachable (); } - void visit (TyTy::FloatType &type) override { gcc_unreachable (); } - void visit (TyTy::ErrorType &type) override { gcc_unreachable (); } - - void visit (TyTy::FnType &type) override - { - ok = true; - translated = type.get_return_type (); - } - -private: - TyTyExtractRetFromFnType () : ok (false), translated (nullptr) {} - - bool ok; - TyTy::TyBase *translated; -}; - } // namespace Compile } // namespace Rust -- cgit v1.1 From 0817c29a423aca1c4c3f9ba812f67df35f36fc65 Mon Sep 17 00:00:00 2001 From: Philip Herron Date: Thu, 21 Jan 2021 17:31:21 +0000 Subject: Add Integer and Float InterenceVariable In order to properly handle all integer types and infer we must follow HM algorithm. This means when we unify every type in the resolver this should keep a chain of HirId of references such that when/if the type is resolved it lookup tables can be updated for the Backend to compile to Gimple. Consider the case: fn test(x:u32) -> u32 {...} let a = test(1); The VarDecl here will have the type let a: = test(1). Since this integer combines with the parameter x:u32 the type resolver knows at this point these must be a u32. let a; a = 1; let b:u32 = a; This is more subtle let a: a: = 1 let b:u32 = a; Since the integer inference variable combines with u32 all previous references can be updated to u32 at this point. In the basic case of: let a; a = 1; This resolves down to: let a:; a = 1 It is not until we complete type-inference we can iterate all the resolved types and HirIds and default any to i32 and any to f32. Any remaining general inference variable are errors. --- gcc/rust/backend/rust-compile-context.h | 31 +++++++++++++++++++++++++++++++ gcc/rust/backend/rust-compile-expr.h | 8 +++++--- gcc/rust/backend/rust-compile-tyty.h | 2 ++ 3 files changed, 38 insertions(+), 3 deletions(-) (limited to 'gcc/rust/backend') diff --git a/gcc/rust/backend/rust-compile-context.h b/gcc/rust/backend/rust-compile-context.h index df29e36..ed03f02 100644 --- a/gcc/rust/backend/rust-compile-context.h +++ b/gcc/rust/backend/rust-compile-context.h @@ -298,6 +298,37 @@ public: translated = named_struct; } + void visit (TyTy::TupleType &type) override + { + bool ok = ctx->lookup_compiled_types (type.get_ty_ref (), &translated); + if (ok) + return; + + // create implicit struct + std::vector fields; + for (size_t i = 0; i < type.num_fields (); i++) + { + TyTy::TyBase *field = type.get_field (i); + Btype *compiled_field_ty + = TyTyCompile::compile (ctx->get_backend (), field); + + Backend::Btyped_identifier f (std::to_string (i), compiled_field_ty, + ctx->get_mappings ()->lookup_location ( + type.get_ty_ref ())); + fields.push_back (std::move (f)); + } + + Btype *struct_type_record = ctx->get_backend ()->struct_type (fields); + Btype *named_struct + = ctx->get_backend ()->named_type (type.as_string (), struct_type_record, + ctx->get_mappings ()->lookup_location ( + type.get_ty_ref ())); + + ctx->push_type (named_struct); + ctx->insert_compiled_type (type.get_ty_ref (), named_struct); + translated = named_struct; + } + void visit (TyTy::ArrayType &type) override { mpz_t ival; diff --git a/gcc/rust/backend/rust-compile-expr.h b/gcc/rust/backend/rust-compile-expr.h index da3c9cd..7c2f32d 100644 --- a/gcc/rust/backend/rust-compile-expr.h +++ b/gcc/rust/backend/rust-compile-expr.h @@ -145,17 +145,19 @@ public: void visit (HIR::LiteralExpr &expr) { + auto literal_value = expr.get_literal (); switch (expr.get_lit_type ()) { case HIR::Literal::BOOL: { - bool bval = expr.as_string ().compare ("true") == 0; + bool bval = literal_value->as_string ().compare ("true") == 0; translated = ctx->get_backend ()->boolean_constant_expression (bval); } return; case HIR::Literal::INT: { mpz_t ival; - if (mpz_init_set_str (ival, expr.as_string ().c_str (), 10) != 0) + if (mpz_init_set_str (ival, literal_value->as_string ().c_str (), 10) + != 0) { rust_fatal_error (expr.get_locus (), "bad number in literal"); return; @@ -178,7 +180,7 @@ public: case HIR::Literal::FLOAT: { mpfr_t fval; - if (mpfr_init_set_str (fval, expr.as_string ().c_str (), 10, + if (mpfr_init_set_str (fval, literal_value->as_string ().c_str (), 10, MPFR_RNDN) != 0) { diff --git a/gcc/rust/backend/rust-compile-tyty.h b/gcc/rust/backend/rust-compile-tyty.h index f74b4ac..b6794bc 100644 --- a/gcc/rust/backend/rust-compile-tyty.h +++ b/gcc/rust/backend/rust-compile-tyty.h @@ -52,6 +52,8 @@ public: void visit (TyTy::ADTType &type) override { gcc_unreachable (); } + void visit (TyTy::TupleType &type) override { gcc_unreachable (); } + void visit (TyTy::ArrayType &type) override { gcc_unreachable (); } void visit (TyTy::UnitType &type) override -- cgit v1.1 From 854aad3b58e747cad3e46b522c9ef765bdfadca4 Mon Sep 17 00:00:00 2001 From: Philip Herron Date: Mon, 25 Jan 2021 13:27:50 +0000 Subject: Add usize and isize types Arrays can only be indexed by usize and this enforces that rule. These types are sized based on the pointer size of the host arch. Fixes #87 --- gcc/rust/backend/rust-compile-context.h | 16 ++++++++++++++++ gcc/rust/backend/rust-compile-tyty.h | 14 ++++++++++++++ 2 files changed, 30 insertions(+) (limited to 'gcc/rust/backend') diff --git a/gcc/rust/backend/rust-compile-context.h b/gcc/rust/backend/rust-compile-context.h index ed03f02..034568f 100644 --- a/gcc/rust/backend/rust-compile-context.h +++ b/gcc/rust/backend/rust-compile-context.h @@ -374,6 +374,22 @@ public: translated = compiled_type; } + void visit (TyTy::USizeType &type) override + { + ::Btype *compiled_type = nullptr; + bool ok = ctx->lookup_compiled_types (type.get_ty_ref (), &compiled_type); + rust_assert (ok); + translated = compiled_type; + } + + void visit (TyTy::ISizeType &type) override + { + ::Btype *compiled_type = nullptr; + bool ok = ctx->lookup_compiled_types (type.get_ty_ref (), &compiled_type); + rust_assert (ok); + translated = compiled_type; + } + private: TyTyResolveCompile (Context *ctx) : ctx (ctx) {} diff --git a/gcc/rust/backend/rust-compile-tyty.h b/gcc/rust/backend/rust-compile-tyty.h index b6794bc..2c54b17 100644 --- a/gcc/rust/backend/rust-compile-tyty.h +++ b/gcc/rust/backend/rust-compile-tyty.h @@ -190,6 +190,20 @@ public: gcc_unreachable (); } + void visit (TyTy::USizeType &type) override + { + translated = backend->named_type ( + "usize", backend->integer_type (true, backend->get_pointer_size ()), + Linemap::predeclared_location ()); + } + + void visit (TyTy::ISizeType &type) override + { + translated = backend->named_type ( + "isize", backend->integer_type (false, backend->get_pointer_size ()), + Linemap::predeclared_location ()); + } + private: TyTyCompile (::Backend *backend) : backend (backend), translated (nullptr), -- cgit v1.1 From 8578c61be5061fab91fe679a15fd68ab5fad987c Mon Sep 17 00:00:00 2001 From: Philip Herron Date: Mon, 25 Jan 2021 17:03:36 +0000 Subject: Add mutablity checks and left hand size assignee checker In order to assign to a name we must ensure the LHS is a valid expression to assign to. This leads onto actually checking if this is a mutable declaration or not. Once these checks pass the name resolver we can in GIMPLE create immutable types for these declarations to help with optimization. Fixes #77 --- gcc/rust/backend/rust-compile-fnparam.h | 67 ++++++++++++++++++++++++++++++++ gcc/rust/backend/rust-compile-item.h | 18 +++++---- gcc/rust/backend/rust-compile-var-decl.h | 3 ++ 3 files changed, 81 insertions(+), 7 deletions(-) create mode 100644 gcc/rust/backend/rust-compile-fnparam.h (limited to 'gcc/rust/backend') diff --git a/gcc/rust/backend/rust-compile-fnparam.h b/gcc/rust/backend/rust-compile-fnparam.h new file mode 100644 index 0000000..cf6e6f7 --- /dev/null +++ b/gcc/rust/backend/rust-compile-fnparam.h @@ -0,0 +1,67 @@ +// Copyright (C) 2020 Free Software Foundation, Inc. + +// This file is part of GCC. + +// GCC 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 3, or (at your option) any later +// version. + +// GCC 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 GCC; see the file COPYING3. If not see +// . + +#ifndef RUST_COMPILE_FNPARAM +#define RUST_COMPILE_FNPARAM + +#include "rust-compile-base.h" + +namespace Rust { +namespace Compile { + +class CompileFnParam : public HIRCompileBase +{ +public: + static Bvariable *compile (Context *ctx, Bfunction *fndecl, + HIR::FunctionParam *param, Btype *decl_type, + Location locus) + { + CompileFnParam compiler (ctx, fndecl, decl_type, locus); + param->get_param_name ()->accept_vis (compiler); + return compiler.translated; + } + + void visit (HIR::IdentifierPattern &pattern) + { + if (!pattern.is_mut) + decl_type = ctx->get_backend ()->immutable_type (decl_type); + + translated + = ctx->get_backend ()->parameter_variable (fndecl, pattern.variable_ident, + decl_type, + false /* address_taken */, + locus); + } + +private: + CompileFnParam (Context *ctx, ::Bfunction *fndecl, ::Btype *decl_type, + Location locus) + : HIRCompileBase (ctx), fndecl (fndecl), decl_type (decl_type), + locus (locus), translated (nullptr) + {} + + ::Bfunction *fndecl; + ::Btype *decl_type; + Location locus; + ::Bvariable *translated; +}; + +} // namespace Compile +} // namespace Rust + +#endif // RUST_COMPILE_FNPARAM diff --git a/gcc/rust/backend/rust-compile-item.h b/gcc/rust/backend/rust-compile-item.h index bf899d8..1bb7c91 100644 --- a/gcc/rust/backend/rust-compile-item.h +++ b/gcc/rust/backend/rust-compile-item.h @@ -24,6 +24,7 @@ #include "rust-compile-var-decl.h" #include "rust-compile-stmt.h" #include "rust-compile-expr.h" +#include "rust-compile-fnparam.h" namespace Rust { namespace Compile { @@ -174,17 +175,20 @@ public: for (auto &it : fntype->get_params ()) { HIR::FunctionParam &referenced_param = function.function_params.at (i); - auto param_pattern = it.first; auto param_tyty = it.second; - auto compiled_param_type = TyTyResolveCompile::compile (ctx, param_tyty); - bool tree_addressable = false; - auto compiled_param_var = ctx->get_backend ()->parameter_variable ( - fndecl, param_pattern->as_string (), compiled_param_type, - tree_addressable, - ctx->get_mappings ()->lookup_location (param_tyty->get_ref ())); + Location param_locus + = ctx->get_mappings ()->lookup_location (param_tyty->get_ref ()); + Bvariable *compiled_param_var + = CompileFnParam::compile (ctx, fndecl, &referenced_param, + compiled_param_type, param_locus); + if (compiled_param_var == nullptr) + { + rust_error_at (param_locus, "failed to compile parameter variable"); + return; + } param_vars.push_back (compiled_param_var); diff --git a/gcc/rust/backend/rust-compile-var-decl.h b/gcc/rust/backend/rust-compile-var-decl.h index cf73820..06ea5a9 100644 --- a/gcc/rust/backend/rust-compile-var-decl.h +++ b/gcc/rust/backend/rust-compile-var-decl.h @@ -54,6 +54,9 @@ public: void visit (HIR::IdentifierPattern &pattern) { + if (!pattern.is_mut) + translated_type = ctx->get_backend ()->immutable_type (translated_type); + translated = ctx->get_backend ()->local_variable (fndecl, pattern.variable_ident, translated_type, NULL /*decl_var*/, -- cgit v1.1 From 244c2d2ea1a5a69ab6f7f50902512c1a7daa29c9 Mon Sep 17 00:00:00 2001 From: Philip Herron Date: Tue, 26 Jan 2021 17:28:52 +0000 Subject: Support binding functions to LetStmts. This supports basic function pointers in rust most of the code was already there to infer this but this has now helped tidy it up and make it work. Fixes #184 --- gcc/rust/backend/rust-compile-expr.h | 28 ++++++++++++++--------- gcc/rust/backend/rust-compile-resolve-path.cc | 32 ++++++++++++++++++++++----- 2 files changed, 44 insertions(+), 16 deletions(-) (limited to 'gcc/rust/backend') diff --git a/gcc/rust/backend/rust-compile-expr.h b/gcc/rust/backend/rust-compile-expr.h index 7c2f32d..81d7786 100644 --- a/gcc/rust/backend/rust-compile-expr.h +++ b/gcc/rust/backend/rust-compile-expr.h @@ -127,20 +127,28 @@ public: return; } - // this could be a constant reference - if (ctx->lookup_const_decl (ref, &translated)) - return; - - // must be an identifier + Bfunction *fn = nullptr; Bvariable *var = nullptr; - if (!ctx->lookup_var_decl (ref, &var)) + if (ctx->lookup_const_decl (ref, &translated)) { - rust_fatal_error (expr.get_locus (), - "failed to lookup compiled variable"); return; } - - translated = ctx->get_backend ()->var_expression (var, expr.get_locus ()); + else if (ctx->lookup_function_decl (ref, &fn)) + { + translated + = ctx->get_backend ()->function_code_expression (fn, + expr.get_locus ()); + } + else if (ctx->lookup_var_decl (ref, &var)) + { + translated + = ctx->get_backend ()->var_expression (var, expr.get_locus ()); + } + else + { + rust_fatal_error (expr.get_locus (), + "failed to lookup compiled reference"); + } } void visit (HIR::LiteralExpr &expr) diff --git a/gcc/rust/backend/rust-compile-resolve-path.cc b/gcc/rust/backend/rust-compile-resolve-path.cc index 37285b7..818d5cb 100644 --- a/gcc/rust/backend/rust-compile-resolve-path.cc +++ b/gcc/rust/backend/rust-compile-resolve-path.cc @@ -28,23 +28,43 @@ void ResolvePathRef::visit (HIR::PathInExpression &expr) { // need to look up the reference for this identifier - NodeId ref_node_id; - if (!ctx->get_resolver ()->lookup_resolved_name ( + NodeId ref_node_id = UNKNOWN_NODEID; + if (ctx->get_resolver ()->lookup_resolved_name ( expr.get_mappings ().get_nodeid (), &ref_node_id)) { - return; + Resolver::Definition def; + if (!ctx->get_resolver ()->lookup_definition (ref_node_id, &def)) + { + rust_error_at (expr.get_locus (), + "unknown reference for resolved name"); + return; + } + ref_node_id = def.parent; } + // this can fail because it might be a Constructor for something + // in that case the caller should attempt ResolvePathType::Compile + if (ref_node_id == UNKNOWN_NODEID) + return; + HirId ref; if (!ctx->get_mappings ()->lookup_node_to_hir ( expr.get_mappings ().get_crate_num (), ref_node_id, &ref)) { - rust_error_at (expr.get_locus (), "reverse lookup failure"); + rust_error_at (expr.get_locus (), "reverse call path lookup failure"); return; } - // assumes paths are functions for now - Bfunction *fn; + // this might be a variable reference or a function reference + Bvariable *var = nullptr; + if (ctx->lookup_var_decl (ref, &var)) + { + resolved = ctx->get_backend ()->var_expression (var, expr.get_locus ()); + return; + } + + // must be a function call + Bfunction *fn = nullptr; if (!ctx->lookup_function_decl (ref, &fn)) { // this might fail because its a forward decl so we can attempt to -- cgit v1.1