diff options
author | Philip Herron <philip.herron@embecosm.com> | 2020-12-15 17:48:11 +0000 |
---|---|---|
committer | Philip Herron <herron.philip@googlemail.com> | 2020-12-17 17:23:46 +0000 |
commit | 6136f0aebbb84cbcf8f92bed206733391aaa3866 (patch) | |
tree | 49c24a3b9c9483bb2755642496bcd0aec3f8c598 | |
parent | a621e19365473b477d121c28a057cc25d3951c76 (diff) | |
download | gcc-6136f0aebbb84cbcf8f92bed206733391aaa3866.zip gcc-6136f0aebbb84cbcf8f92bed206733391aaa3866.tar.gz gcc-6136f0aebbb84cbcf8f92bed206733391aaa3866.tar.bz2 |
This is a new HIR -> GIMPLE pass it reuses the mappings from hir,
name resolution and type resolution to simplify the generation of
gimple.
32 files changed, 1738 insertions, 99 deletions
diff --git a/gcc/rust/Make-lang.in b/gcc/rust/Make-lang.in index 56f308e..5ac60ea 100644 --- a/gcc/rust/Make-lang.in +++ b/gcc/rust/Make-lang.in @@ -70,6 +70,7 @@ GRS_OBJS = \ rust/rust-ast-full-test.o \ rust/rust-session-manager.o \ rust/rust-compile.o \ + rust/rust-compile-resolve-path.o \ rust/rust-macro-expand.o \ rust/rust-hir-full-test.o \ rust/rust-hir-map.o \ diff --git a/gcc/rust/backend/rust-compile-base.h b/gcc/rust/backend/rust-compile-base.h new file mode 100644 index 0000000..6410fd4 --- /dev/null +++ b/gcc/rust/backend/rust-compile-base.h @@ -0,0 +1,249 @@ + + +// 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 +// <http://www.gnu.org/licenses/>. + +#ifndef RUST_COMPILE_BASE +#define RUST_COMPILE_BASE + +#include "rust-compile-context.h" +#include "rust-hir-visitor.h" +#include "rust-hir-full.h" + +namespace Rust { +namespace Compile { + +class HIRCompileBase : public HIR::HIRVisitor +{ +public: + virtual ~HIRCompileBase () {} + + // rust-ast.h + // virtual void visit(AttrInput& attr_input) {} + // virtual void visit(TokenTree& token_tree) {} + // virtual void visit(MacroMatch& macro_match) {} + virtual void visit (HIR::Token &tok) {} + virtual void visit (HIR::DelimTokenTree &delim_tok_tree) {} + virtual void visit (HIR::AttrInputMetaItemContainer &input) {} + // virtual void visit(MetaItem& meta_item) {} + // virtual void visit(Stmt& stmt) {} + // virtual void visit(Expr& expr) {} + virtual void visit (HIR::IdentifierExpr &ident_expr) {} + // virtual void visit(Pattern& pattern) {} + // virtual void visit(Type& type) {} + // virtual void visit(TypeParamBound& type_param_bound) {} + virtual void visit (HIR::Lifetime &lifetime) {} + // virtual void visit(GenericParam& generic_param) {} + virtual void visit (HIR::LifetimeParam &lifetime_param) {} + // virtual void visit(TraitItem& trait_item) {} + // virtual void visit(InherentImplItem& inherent_impl_item) {} + // virtual void visit(TraitImplItem& trait_impl_item) {} + virtual void visit (HIR::MacroInvocationSemi ¯o) {} + + // rust-path.h + virtual void visit (HIR::PathInExpression &path) {} + virtual void visit (HIR::TypePathSegment &segment) {} + virtual void visit (HIR::TypePathSegmentGeneric &segment) {} + virtual void visit (HIR::TypePathSegmentFunction &segment) {} + virtual void visit (HIR::TypePath &path) {} + virtual void visit (HIR::QualifiedPathInExpression &path) {} + virtual void visit (HIR::QualifiedPathInType &path) {} + + // rust-expr.h + virtual void visit (HIR::LiteralExpr &expr) {} + virtual void visit (HIR::AttrInputLiteral &attr_input) {} + virtual void visit (HIR::MetaItemLitExpr &meta_item) {} + virtual void visit (HIR::MetaItemPathLit &meta_item) {} + virtual void visit (HIR::BorrowExpr &expr) {} + virtual void visit (HIR::DereferenceExpr &expr) {} + virtual void visit (HIR::ErrorPropagationExpr &expr) {} + virtual void visit (HIR::NegationExpr &expr) {} + virtual void visit (HIR::ArithmeticOrLogicalExpr &expr) {} + virtual void visit (HIR::ComparisonExpr &expr) {} + virtual void visit (HIR::LazyBooleanExpr &expr) {} + virtual void visit (HIR::TypeCastExpr &expr) {} + virtual void visit (HIR::AssignmentExpr &expr) {} + virtual void visit (HIR::CompoundAssignmentExpr &expr) {} + virtual void visit (HIR::GroupedExpr &expr) {} + // virtual void visit(ArrayElems& elems) {} + virtual void visit (HIR::ArrayElemsValues &elems) {} + virtual void visit (HIR::ArrayElemsCopied &elems) {} + virtual void visit (HIR::ArrayExpr &expr) {} + virtual void visit (HIR::ArrayIndexExpr &expr) {} + virtual void visit (HIR::TupleExpr &expr) {} + virtual void visit (HIR::TupleIndexExpr &expr) {} + virtual void visit (HIR::StructExprStruct &expr) {} + // virtual void visit(StructExprField& field) {} + virtual void visit (HIR::StructExprFieldIdentifier &field) {} + virtual void visit (HIR::StructExprFieldIdentifierValue &field) {} + virtual void visit (HIR::StructExprFieldIndexValue &field) {} + virtual void visit (HIR::StructExprStructFields &expr) {} + virtual void visit (HIR::StructExprStructBase &expr) {} + virtual void visit (HIR::StructExprTuple &expr) {} + virtual void visit (HIR::StructExprUnit &expr) {} + // virtual void visit(EnumExprField& field) {} + virtual void visit (HIR::EnumExprFieldIdentifier &field) {} + virtual void visit (HIR::EnumExprFieldIdentifierValue &field) {} + virtual void visit (HIR::EnumExprFieldIndexValue &field) {} + virtual void visit (HIR::EnumExprStruct &expr) {} + virtual void visit (HIR::EnumExprTuple &expr) {} + virtual void visit (HIR::EnumExprFieldless &expr) {} + virtual void visit (HIR::CallExpr &expr) {} + virtual void visit (HIR::MethodCallExpr &expr) {} + virtual void visit (HIR::FieldAccessExpr &expr) {} + virtual void visit (HIR::ClosureExprInner &expr) {} + virtual void visit (HIR::BlockExpr &expr) {} + virtual void visit (HIR::ClosureExprInnerTyped &expr) {} + virtual void visit (HIR::ContinueExpr &expr) {} + virtual void visit (HIR::BreakExpr &expr) {} + virtual void visit (HIR::RangeFromToExpr &expr) {} + virtual void visit (HIR::RangeFromExpr &expr) {} + virtual void visit (HIR::RangeToExpr &expr) {} + virtual void visit (HIR::RangeFullExpr &expr) {} + virtual void visit (HIR::RangeFromToInclExpr &expr) {} + virtual void visit (HIR::RangeToInclExpr &expr) {} + virtual void visit (HIR::ReturnExpr &expr) {} + virtual void visit (HIR::UnsafeBlockExpr &expr) {} + virtual void visit (HIR::LoopExpr &expr) {} + virtual void visit (HIR::WhileLoopExpr &expr) {} + virtual void visit (HIR::WhileLetLoopExpr &expr) {} + virtual void visit (HIR::ForLoopExpr &expr) {} + virtual void visit (HIR::IfExpr &expr) {} + virtual void visit (HIR::IfExprConseqElse &expr) {} + virtual void visit (HIR::IfExprConseqIf &expr) {} + virtual void visit (HIR::IfExprConseqIfLet &expr) {} + virtual void visit (HIR::IfLetExpr &expr) {} + virtual void visit (HIR::IfLetExprConseqElse &expr) {} + virtual void visit (HIR::IfLetExprConseqIf &expr) {} + virtual void visit (HIR::IfLetExprConseqIfLet &expr) {} + // virtual void visit(MatchCase& match_case) {} + // virtual void visit (HIR::MatchCaseBlockExpr &match_case) {} + // virtual void visit (HIR::MatchCaseExpr &match_case) {} + virtual void visit (HIR::MatchExpr &expr) {} + virtual void visit (HIR::AwaitExpr &expr) {} + virtual void visit (HIR::AsyncBlockExpr &expr) {} + + // rust-item.h + virtual void visit (HIR::TypeParam ¶m) {} + // virtual void visit(WhereClauseItem& item) {} + virtual void visit (HIR::LifetimeWhereClauseItem &item) {} + virtual void visit (HIR::TypeBoundWhereClauseItem &item) {} + virtual void visit (HIR::Method &method) {} + virtual void visit (HIR::ModuleBodied &module) {} + virtual void visit (HIR::ModuleNoBody &module) {} + virtual void visit (HIR::ExternCrate &crate) {} + // virtual void visit(UseTree& use_tree) {} + virtual void visit (HIR::UseTreeGlob &use_tree) {} + virtual void visit (HIR::UseTreeList &use_tree) {} + virtual void visit (HIR::UseTreeRebind &use_tree) {} + virtual void visit (HIR::UseDeclaration &use_decl) {} + virtual void visit (HIR::Function &function) {} + virtual void visit (HIR::TypeAlias &type_alias) {} + virtual void visit (HIR::StructStruct &struct_item) {} + virtual void visit (HIR::TupleStruct &tuple_struct) {} + virtual void visit (HIR::EnumItem &item) {} + virtual void visit (HIR::EnumItemTuple &item) {} + virtual void visit (HIR::EnumItemStruct &item) {} + virtual void visit (HIR::EnumItemDiscriminant &item) {} + virtual void visit (HIR::Enum &enum_item) {} + virtual void visit (HIR::Union &union_item) {} + virtual void visit (HIR::ConstantItem &const_item) {} + virtual void visit (HIR::StaticItem &static_item) {} + virtual void visit (HIR::TraitItemFunc &item) {} + virtual void visit (HIR::TraitItemMethod &item) {} + virtual void visit (HIR::TraitItemConst &item) {} + virtual void visit (HIR::TraitItemType &item) {} + virtual void visit (HIR::Trait &trait) {} + virtual void visit (HIR::InherentImpl &impl) {} + virtual void visit (HIR::TraitImpl &impl) {} + // virtual void visit(ExternalItem& item) {} + virtual void visit (HIR::ExternalStaticItem &item) {} + virtual void visit (HIR::ExternalFunctionItem &item) {} + virtual void visit (HIR::ExternBlock &block) {} + + // rust-macro.h + virtual void visit (HIR::MacroMatchFragment &match) {} + virtual void visit (HIR::MacroMatchRepetition &match) {} + virtual void visit (HIR::MacroMatcher &matcher) {} + virtual void visit (HIR::MacroRulesDefinition &rules_def) {} + virtual void visit (HIR::MacroInvocation ¯o_invoc) {} + virtual void visit (HIR::MetaItemPath &meta_item) {} + virtual void visit (HIR::MetaItemSeq &meta_item) {} + virtual void visit (HIR::MetaWord &meta_item) {} + virtual void visit (HIR::MetaNameValueStr &meta_item) {} + virtual void visit (HIR::MetaListPaths &meta_item) {} + virtual void visit (HIR::MetaListNameValueStr &meta_item) {} + + // rust-pattern.h + virtual void visit (HIR::LiteralPattern &pattern) {} + virtual void visit (HIR::IdentifierPattern &pattern) {} + virtual void visit (HIR::WildcardPattern &pattern) {} + // virtual void visit(RangePatternBound& bound) {} + virtual void visit (HIR::RangePatternBoundLiteral &bound) {} + virtual void visit (HIR::RangePatternBoundPath &bound) {} + virtual void visit (HIR::RangePatternBoundQualPath &bound) {} + virtual void visit (HIR::RangePattern &pattern) {} + virtual void visit (HIR::ReferencePattern &pattern) {} + // virtual void visit(StructPatternField& field) {} + virtual void visit (HIR::StructPatternFieldTuplePat &field) {} + virtual void visit (HIR::StructPatternFieldIdentPat &field) {} + virtual void visit (HIR::StructPatternFieldIdent &field) {} + virtual void visit (HIR::StructPattern &pattern) {} + // virtual void visit(TupleStructItems& tuple_items) {} + virtual void visit (HIR::TupleStructItemsNoRange &tuple_items) {} + virtual void visit (HIR::TupleStructItemsRange &tuple_items) {} + virtual void visit (HIR::TupleStructPattern &pattern) {} + // virtual void visit(TuplePatternItems& tuple_items) {} + virtual void visit (HIR::TuplePatternItemsMultiple &tuple_items) {} + virtual void visit (HIR::TuplePatternItemsRanged &tuple_items) {} + virtual void visit (HIR::TuplePattern &pattern) {} + virtual void visit (HIR::GroupedPattern &pattern) {} + virtual void visit (HIR::SlicePattern &pattern) {} + + // rust-stmt.h + virtual void visit (HIR::EmptyStmt &stmt) {} + virtual void visit (HIR::LetStmt &stmt) {} + virtual void visit (HIR::ExprStmtWithoutBlock &stmt) {} + virtual void visit (HIR::ExprStmtWithBlock &stmt) {} + + // rust-type.h + virtual void visit (HIR::TraitBound &bound) {} + virtual void visit (HIR::ImplTraitType &type) {} + virtual void visit (HIR::TraitObjectType &type) {} + virtual void visit (HIR::ParenthesisedType &type) {} + virtual void visit (HIR::ImplTraitTypeOneBound &type) {} + virtual void visit (HIR::TraitObjectTypeOneBound &type) {} + virtual void visit (HIR::TupleType &type) {} + virtual void visit (HIR::NeverType &type) {} + virtual void visit (HIR::RawPointerType &type) {} + virtual void visit (HIR::ReferenceType &type) {} + virtual void visit (HIR::ArrayType &type) {} + virtual void visit (HIR::SliceType &type) {} + virtual void visit (HIR::InferredType &type) {} + virtual void visit (HIR::BareFunctionType &type) {} + +protected: + HIRCompileBase (Context *ctx) : ctx (ctx) {} + + Context *get_context () { return ctx; } + + Context *ctx; +}; + +} // namespace Compile +} // namespace Rust + +#endif // RUST_COMPILE_BASE diff --git a/gcc/rust/backend/rust-compile-context.h b/gcc/rust/backend/rust-compile-context.h new file mode 100644 index 0000000..f890678 --- /dev/null +++ b/gcc/rust/backend/rust-compile-context.h @@ -0,0 +1,247 @@ +// 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 +// <http://www.gnu.org/licenses/>. + +#ifndef RUST_COMPILE_CONTEXT +#define RUST_COMPILE_CONTEXT + +#include "rust-system.h" +#include "rust-hir-map.h" +#include "rust-name-resolver.h" +#include "rust-hir-type-check.h" +#include "rust-backend.h" +#include "rust-compile-tyty.h" +#include "rust-ast-full.h" + +namespace Rust { +namespace Compile { + +struct fncontext +{ + ::Bfunction *fndecl; + ::Bvariable *ret_addr; +}; + +class Context +{ +public: + Context (::Backend *backend) + : backend (backend), resolver (Resolver::Resolver::get ()), + tyctx (Resolver::TypeCheckContext::get ()), + mappings (Analysis::Mappings::get ()) + { + // insert the builtins + auto builtins = resolver->get_builtin_types (); + for (auto it = builtins.begin (); it != builtins.end (); it++) + { + HirId ref; + rust_assert ( + tyctx->lookup_type_by_node_id ((*it)->get_node_id (), &ref)); + + TyTy::TyBase *lookup; + rust_assert (tyctx->lookup_type (ref, &lookup)); + + auto compiled = TyTyCompile::compile (backend, lookup); + compiled_type_map[ref] = compiled; + } + } + + ~Context () {} + + bool lookup_compiled_types (HirId id, ::Btype **type) + { + auto it = compiled_type_map.find (id); + if (it == compiled_type_map.end ()) + return false; + + *type = it->second; + return true; + } + + void insert_compiled_type (HirId id, ::Btype *type) + { + compiled_type_map[id] = type; + } + + ::Backend *get_backend () { return backend; } + Resolver::Resolver *get_resolver () { return resolver; } + Resolver::TypeCheckContext *get_tyctx () { return tyctx; } + Analysis::Mappings *get_mappings () { return mappings; } + + void push_block (Bblock *scope) + { + scope_stack.push_back (scope); + statements.push_back ({}); + } + + Bblock *pop_block () + { + auto block = scope_stack.back (); + scope_stack.pop_back (); + + auto stmts = statements.back (); + statements.pop_back (); + + backend->block_add_statements (block, stmts); + + return block; + } + + Bblock *peek_enclosing_scope () + { + if (scope_stack.size () == 0) + return nullptr; + + return scope_stack.back (); + } + + void add_statement (Bstatement *stmt) { statements.back ().push_back (stmt); } + + void insert_var_decl (HirId id, ::Bvariable *decl) + { + compiled_var_decls[id] = decl; + } + + bool lookup_var_decl (HirId id, ::Bvariable **decl) + { + auto it = compiled_var_decls.find (id); + if (it == compiled_var_decls.end ()) + return false; + + *decl = it->second; + return true; + } + + void insert_function_decl (HirId id, ::Bfunction *fn) + { + compiled_fn_map[id] = fn; + } + + bool lookup_function_decl (HirId id, ::Bfunction **fn) + { + auto it = compiled_fn_map.find (id); + if (it == compiled_fn_map.end ()) + return false; + + *fn = it->second; + return true; + } + + void push_fn (::Bfunction *fn, ::Bvariable *ret_addr) + { + fn_stack.push_back (fncontext{fn, ret_addr}); + } + void pop_fn () { fn_stack.pop_back (); } + fncontext peek_fn () { return fn_stack.back (); } + + void push_type (::Btype *t) { type_decls.push_back (t); } + void push_var (::Bvariable *v) { var_decls.push_back (v); } + void push_const (::Bexpression *c) { const_decls.push_back (c); } + void push_function (::Bfunction *f) { func_decls.push_back (f); } + + void write_to_backend () + { + backend->write_global_definitions (type_decls, const_decls, func_decls, + var_decls); + } + + bool function_completed (Bfunction *fn) + { + for (auto it = func_decls.begin (); it != func_decls.end (); it++) + { + Bfunction *i = (*it); + if (i == fn) + { + return true; + } + } + return false; + } + +private: + ::Backend *backend; + Resolver::Resolver *resolver; + Resolver::TypeCheckContext *tyctx; + Analysis::Mappings *mappings; + + // state + std::vector<fncontext> fn_stack; + std::map<HirId, ::Bvariable *> compiled_var_decls; + std::map<HirId, ::Btype *> compiled_type_map; + std::map<HirId, ::Bfunction *> compiled_fn_map; + std::vector< ::std::vector<Bstatement *> > statements; + std::vector< ::Bblock *> scope_stack; + + // To GCC middle-end + std::vector< ::Btype *> type_decls; + std::vector< ::Bvariable *> var_decls; + std::vector< ::Bexpression *> const_decls; + std::vector< ::Bfunction *> func_decls; +}; + +class TyTyResolveCompile : public TyTy::TyVisitor +{ +public: + static ::Btype *compile (Context *ctx, TyTy::TyBase *ty) + { + TyTyResolveCompile compiler (ctx); + ty->accept_vis (compiler); + return compiler.translated; + } + + virtual ~TyTyResolveCompile () {} + + void visit (TyTy::FnType &type) { gcc_unreachable (); } + + void visit (TyTy::BoolType &type) + { + ::Btype *compiled_type = nullptr; + bool ok = ctx->lookup_compiled_types (type.get_ref (), &compiled_type); + rust_assert (ok); + translated = compiled_type; + } + + void visit (TyTy::IntType &type) + { + printf ("type [%s] has ref: %u\n", type.as_string ().c_str (), + type.get_ref ()); + + ::Btype *compiled_type = nullptr; + bool ok = ctx->lookup_compiled_types (type.get_ref (), &compiled_type); + rust_assert (ok); + translated = compiled_type; + } + + void visit (TyTy::UintType &type) + { + ::Btype *compiled_type = nullptr; + bool ok = ctx->lookup_compiled_types (type.get_ref (), &compiled_type); + rust_assert (ok); + translated = compiled_type; + } + +private: + TyTyResolveCompile (Context *ctx) : ctx (ctx) {} + + Context *ctx; + ::Btype *translated; +}; + +} // namespace Compile +} // namespace Rust + +#endif // RUST_COMPILE_CONTEXT diff --git a/gcc/rust/backend/rust-compile-expr.h b/gcc/rust/backend/rust-compile-expr.h new file mode 100644 index 0000000..7808af2 --- /dev/null +++ b/gcc/rust/backend/rust-compile-expr.h @@ -0,0 +1,285 @@ +// 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 +// <http://www.gnu.org/licenses/>. + +#ifndef RUST_COMPILE_EXPR +#define RUST_COMPILE_EXPR + +#include "rust-compile-base.h" +#include "rust-compile-tyty.h" +#include "rust-compile-resolve-path.h" + +namespace Rust { +namespace Compile { + +class CompileExpr : public HIRCompileBase +{ +public: + static Bexpression *Compile (HIR::Expr *expr, Context *ctx) + { + CompileExpr compiler (ctx); + expr->accept_vis (compiler); + return compiler.translated; + } + + virtual ~CompileExpr () {} + + void visit (HIR::ReturnExpr &expr) + { + Bexpression *compiled_expr + = CompileExpr::Compile (expr.return_expr.get (), ctx); + rust_assert (compiled_expr != nullptr); + + auto fncontext = ctx->peek_fn (); + + std::vector<Bexpression *> retstmts; + retstmts.push_back (compiled_expr); + auto s = ctx->get_backend ()->return_statement (fncontext.fndecl, retstmts, + expr.get_locus ()); + ctx->add_statement (s); + } + + void visit (HIR::CallExpr &expr) + { + Bexpression *fn = ResolvePath::Compile (expr.get_fnexpr (), ctx); + rust_assert (fn != nullptr); + + std::vector<Bexpression *> 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::IdentifierExpr &expr) + { + // need to look up the reference for this identifier + NodeId ref_node_id; + 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; + } + + 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; + if (!ctx->get_resolver ()->lookup_definition (ref_node_id, &def)) + { + rust_error_at (expr.get_locus (), "unknown reference"); + return; + } + + HirId ref; + if (!ctx->get_mappings ()->lookup_node_to_hir ( + expr.get_mappings ().get_crate_num (), def.parent, &ref)) + { + rust_fatal_error (expr.get_locus (), "reverse lookup failure"); + return; + } + + Bvariable *var = nullptr; + if (!ctx->lookup_var_decl (ref, &var)) + { + rust_fatal_error (expr.get_locus (), + "failed to lookup compiled variable"); + return; + } + + translated = ctx->get_backend ()->var_expression (var, expr.get_locus ()); + } + + void visit (HIR::LiteralExpr &expr) + { + switch (expr.get_lit_type ()) + { + case HIR::Literal::BOOL: { + bool bval = expr.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) + { + rust_fatal_error (expr.get_locus (), "bad number in literal"); + return; + } + + 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 literal expr"); + return; + } + + Btype *type = TyTyResolveCompile::compile (ctx, tyty); + translated + = ctx->get_backend ()->integer_constant_expression (type, ival); + } + return; + + default: + rust_fatal_error (expr.get_locus (), "unknown literal"); + return; + } + + gcc_unreachable (); + } + + void visit (HIR::AssignmentExpr &expr) + { + fncontext fn = ctx->peek_fn (); + auto lhs = CompileExpr::Compile (expr.get_lhs (), ctx); + auto rhs = CompileExpr::Compile (expr.get_rhs (), ctx); + + Bstatement *assignment + = ctx->get_backend ()->assignment_statement (fn.fndecl, lhs, rhs, + expr.get_locus ()); + ctx->add_statement (assignment); + } + + void visit (HIR::ArithmeticOrLogicalExpr &expr) + { + Operator op; + switch (expr.get_expr_type ()) + { + case HIR::ArithmeticOrLogicalExpr::ADD: + op = OPERATOR_PLUS; + break; + case HIR::ArithmeticOrLogicalExpr::SUBTRACT: + op = OPERATOR_MINUS; + break; + case HIR::ArithmeticOrLogicalExpr::MULTIPLY: + op = OPERATOR_MULT; + break; + case HIR::ArithmeticOrLogicalExpr::DIVIDE: + op = OPERATOR_DIV; + break; + case HIR::ArithmeticOrLogicalExpr::MODULUS: + op = OPERATOR_MOD; + break; + case HIR::ArithmeticOrLogicalExpr::BITWISE_AND: + op = OPERATOR_AND; + break; + case HIR::ArithmeticOrLogicalExpr::BITWISE_OR: + op = OPERATOR_OR; + break; + case HIR::ArithmeticOrLogicalExpr::BITWISE_XOR: + op = OPERATOR_XOR; + break; + case HIR::ArithmeticOrLogicalExpr::LEFT_SHIFT: + op = OPERATOR_LSHIFT; + break; + case HIR::ArithmeticOrLogicalExpr::RIGHT_SHIFT: + op = OPERATOR_RSHIFT; + break; + default: + rust_fatal_error (expr.get_locus (), "failed to compile operator"); + return; + } + + auto lhs = CompileExpr::Compile (expr.get_lhs (), ctx); + auto rhs = CompileExpr::Compile (expr.get_rhs (), ctx); + + translated = ctx->get_backend ()->binary_expression (op, lhs, rhs, + expr.get_locus ()); + } + + void visit (HIR::ComparisonExpr &expr) + { + Operator op; + switch (expr.get_expr_type ()) + { + case HIR::ComparisonExpr::EQUAL: + op = OPERATOR_EQEQ; + break; + case HIR::ComparisonExpr::NOT_EQUAL: + op = OPERATOR_NOTEQ; + break; + case HIR::ComparisonExpr::GREATER_THAN: + op = OPERATOR_GT; + break; + case HIR::ComparisonExpr::LESS_THAN: + op = OPERATOR_LT; + break; + case HIR::ComparisonExpr::GREATER_OR_EQUAL: + op = OPERATOR_GE; + break; + case HIR::ComparisonExpr::LESS_OR_EQUAL: + op = OPERATOR_LE; + break; + default: + rust_fatal_error (expr.get_locus (), "failed to compile operator"); + return; + } + + auto lhs = CompileExpr::Compile (expr.get_lhs (), ctx); + auto rhs = CompileExpr::Compile (expr.get_rhs (), ctx); + + translated = ctx->get_backend ()->binary_expression (op, lhs, rhs, + expr.get_locus ()); + } + + void visit (HIR::LazyBooleanExpr &expr) + { + Operator op; + switch (expr.get_expr_type ()) + { + case HIR::LazyBooleanExpr::LOGICAL_OR: + op = OPERATOR_OROR; + break; + case HIR::LazyBooleanExpr::LOGICAL_AND: + op = OPERATOR_ANDAND; + break; + default: + rust_fatal_error (expr.get_locus (), "failed to compile operator"); + return; + } + + auto lhs = CompileExpr::Compile (expr.get_lhs (), ctx); + auto rhs = CompileExpr::Compile (expr.get_rhs (), ctx); + + translated = ctx->get_backend ()->binary_expression (op, lhs, rhs, + expr.get_locus ()); + } + +private: + CompileExpr (Context *ctx) : HIRCompileBase (ctx), translated (nullptr) {} + + Bexpression *translated; +}; + +} // namespace Compile +} // namespace Rust + +#endif // RUST_COMPILE_EXPR diff --git a/gcc/rust/backend/rust-compile-item.h b/gcc/rust/backend/rust-compile-item.h new file mode 100644 index 0000000..dd07435 --- /dev/null +++ b/gcc/rust/backend/rust-compile-item.h @@ -0,0 +1,180 @@ +// 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 +// <http://www.gnu.org/licenses/>. + +#ifndef RUST_COMPILE_ITEM +#define RUST_COMPILE_ITEM + +#include "rust-compile-base.h" +#include "rust-compile-tyty.h" +#include "rust-compile-var-decl.h" +#include "rust-compile-stmt.h" + +namespace Rust { +namespace Compile { + +class CompileItem : public HIRCompileBase +{ +public: + static void compile (HIR::Item *item, Context *ctx) + { + CompileItem compiler (ctx); + item->accept_vis (compiler); + } + + virtual ~CompileItem () {} + + void visit (HIR::Function &function) + { + // items can be forward compiled which means we may not need to invoke this + // code + Bfunction *lookup = nullptr; + if (ctx->lookup_function_decl (function.get_mappings ().get_hirid (), + &lookup)) + { + // has this been added to the list then it must be finished + if (ctx->function_completed (lookup)) + { + printf ("returning early the function [%s] is completed!\n", + function.as_string ().c_str ()); + return; + } + } + + TyTy::TyBase *fnType; + if (!ctx->get_tyctx ()->lookup_type (function.get_mappings ().get_hirid (), + &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); + + Bfunction *fndecl + = ctx->get_backend ()->function (compiled_fn_type, function.function_name, + "" /* asm_name */, 0 /* flags */, + function.get_locus ()); + ctx->insert_function_decl (function.get_mappings ().get_hirid (), fndecl); + + // setup the params + TyTy::TyBase *tyret = TyTyExtractRetFromFnType::compile (fnType); + std::vector<TyTy::ParamType *> typarams + = TyTyExtractParamsFromFnType::compile (fnType); + std::vector<Bvariable *> param_vars; + + for (auto &it : typarams) + { + auto compiled_param + = TyTyCompileParam::compile (ctx->get_backend (), fndecl, it); + param_vars.push_back (compiled_param); + + ctx->insert_var_decl (it->get_ref (), compiled_param); + } + + if (!ctx->get_backend ()->function_set_parameters (fndecl, param_vars)) + { + rust_fatal_error (function.get_locus (), + "failed to setup parameter variables"); + return; + } + + // lookup locals + auto block_expr = function.function_body.get (); + auto body_mappings = block_expr->get_mappings (); + + Resolver::Rib *rib = nullptr; + if (!ctx->get_resolver ()->find_name_rib (body_mappings.get_nodeid (), + &rib)) + { + rust_fatal_error (function.get_locus (), + "failed to setup locals per block"); + return; + } + + std::vector<Bvariable *> locals; + rib->iterate_decls ([&] (NodeId n) mutable -> bool { + Resolver::Definition d; + bool ok = ctx->get_resolver ()->lookup_definition (n, &d); + rust_assert (ok); + + HIR::Stmt *decl = nullptr; + ok = ctx->get_mappings ()->resolve_nodeid_to_stmt (d.parent, &decl); + rust_assert (ok); + + Bvariable *compiled = CompileVarDecl::compile (fndecl, decl, ctx); + locals.push_back (compiled); + + return true; + }); + + Bblock *enclosing_scope = ctx->peek_enclosing_scope (); + HIR::BlockExpr *function_body = function.function_body.get (); + + Location start_location = function_body->get_locus (); + Location end_location = function_body->get_closing_locus (); + + Bblock *code_block + = ctx->get_backend ()->block (fndecl, enclosing_scope, locals, + start_location, end_location); + ctx->push_block (code_block); + + Bvariable *return_address = nullptr; + if (function.has_function_return_type ()) + { + Btype *return_type = TyTyCompile::compile (ctx->get_backend (), tyret); + + bool address_is_taken = false; + Bstatement *ret_var_stmt = nullptr; + + return_address = ctx->get_backend ()->temporary_variable ( + fndecl, code_block, return_type, NULL, address_is_taken, + function.get_locus (), &ret_var_stmt); + + ctx->add_statement (ret_var_stmt); + } + + ctx->push_fn (fndecl, return_address); + + // compile the block + function_body->iterate_stmts ([&] (HIR::Stmt *s) mutable -> bool { + CompileStmt::Compile (s, ctx); + return true; + }); + + ctx->pop_block (); + auto body = ctx->get_backend ()->block_statement (code_block); + if (!ctx->get_backend ()->function_set_body (fndecl, body)) + { + rust_error_at (function.get_locus (), "failed to set body to function"); + return; + } + + ctx->pop_fn (); + + ctx->push_function (fndecl); + } + +private: + CompileItem (Context *ctx) : HIRCompileBase (ctx) {} +}; + +} // namespace Compile +} // namespace Rust + +#endif // RUST_COMPILE_ITEM diff --git a/gcc/rust/backend/rust-compile-resolve-path.cc b/gcc/rust/backend/rust-compile-resolve-path.cc new file mode 100644 index 0000000..e6683fa --- /dev/null +++ b/gcc/rust/backend/rust-compile-resolve-path.cc @@ -0,0 +1,81 @@ +// 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 +// <http://www.gnu.org/licenses/>. + +#include "rust-linemap.h" +#include "rust-backend.h" +#include "rust-compile-resolve-path.h" +#include "rust-compile-item.h" + +namespace Rust { +namespace Compile { + +void +ResolvePath::visit (HIR::PathInExpression &expr) +{ + // need to look up the reference for this identifier + NodeId ref_node_id; + 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; + } + + printf ("PATHIN have ast node id %u ref %u for expr [%s]\n", + expr.get_mappings ().get_nodeid (), ref_node_id, + expr.as_string ().c_str ()); + + HirId ref; + 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"); + return; + } + + // assumes paths are functions for now + Bfunction *fn; + if (!ctx->lookup_function_decl (ref, &fn)) + { + printf ( + "path failed to lookup function attempting to forward resolve!\n"); + + // this might fail because its a forward decl so we can attempt to + // resolve it now + HIR::Item *resolved_item = ctx->get_mappings ()->lookup_hir_item ( + expr.get_mappings ().get_crate_num (), ref); + if (resolved_item == nullptr) + { + rust_fatal_error (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"); + return; + } + } + + resolved + = ctx->get_backend ()->function_code_expression (fn, expr.get_locus ()); +} + +} // namespace Compile +} // namespace Rust diff --git a/gcc/rust/backend/rust-compile-resolve-path.h b/gcc/rust/backend/rust-compile-resolve-path.h new file mode 100644 index 0000000..d8f393d --- /dev/null +++ b/gcc/rust/backend/rust-compile-resolve-path.h @@ -0,0 +1,52 @@ +// 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 +// <http://www.gnu.org/licenses/>. + +#ifndef RUST_COMPILE_RESOLVE_PATH +#define RUST_COMPILE_RESOLVE_PATH + +#include "rust-compile-base.h" +#include "rust-compile-tyty.h" + +namespace Rust { +namespace Compile { + +class ResolvePath : public HIRCompileBase +{ +public: + static Bexpression *Compile (HIR::Expr *expr, Context *ctx) + { + ResolvePath resolver (ctx); + expr->accept_vis (resolver); + rust_assert (resolver.resolved != nullptr); + return resolver.resolved; + } + + virtual ~ResolvePath () {} + + void visit (HIR::PathInExpression &expr); + +private: + ResolvePath (Context *ctx) : HIRCompileBase (ctx), resolved (nullptr) {} + + Bexpression *resolved; +}; + +} // namespace Compile +} // namespace Rust + +#endif // RUST_COMPILE_RESOLVE_PATH diff --git a/gcc/rust/backend/rust-compile-stmt.h b/gcc/rust/backend/rust-compile-stmt.h new file mode 100644 index 0000000..0a08130 --- /dev/null +++ b/gcc/rust/backend/rust-compile-stmt.h @@ -0,0 +1,85 @@ +// 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 +// <http://www.gnu.org/licenses/>. + +#ifndef RUST_COMPILE_STMT +#define RUST_COMPILE_STMT + +#include "rust-compile-base.h" +#include "rust-compile-tyty.h" +#include "rust-compile-expr.h" + +namespace Rust { +namespace Compile { + +class CompileStmt : public HIRCompileBase +{ +public: + static void Compile (HIR::Stmt *stmt, Context *ctx) + { + CompileStmt compiler (ctx); + stmt->accept_vis (compiler); + rust_assert (compiler.ok); + } + + virtual ~CompileStmt () {} + + void visit (HIR::ExprStmtWithoutBlock &stmt) + { + ok = true; + auto translated = CompileExpr::Compile (stmt.get_expr (), ctx); + + // these can be null + if (translated == nullptr) + return; + + gcc_unreachable (); + } + + void visit (HIR::LetStmt &stmt) + { + // marks that the statement has been looked at + ok = true; + + // nothing to do + if (!stmt.has_init_expr ()) + return; + + Bvariable *var = nullptr; + if (!ctx->lookup_var_decl (stmt.get_mappings ().get_hirid (), &var)) + { + rust_fatal_error (stmt.get_locus (), + "failed to lookup compiled variable decl"); + return; + } + + auto *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); + } + +private: + CompileStmt (Context *ctx) : HIRCompileBase (ctx), ok (false) {} + + bool ok; +}; + +} // namespace Compile +} // namespace Rust + +#endif // RUST_COMPILE_STMT diff --git a/gcc/rust/backend/rust-compile-tyty.h b/gcc/rust/backend/rust-compile-tyty.h new file mode 100644 index 0000000..66d2472 --- /dev/null +++ b/gcc/rust/backend/rust-compile-tyty.h @@ -0,0 +1,247 @@ +// 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 +// <http://www.gnu.org/licenses/>. + +#ifndef RUST_COMPILE_TYTY +#define RUST_COMPILE_TYTY + +#include "rust-system.h" +#include "rust-location.h" +#include "rust-diagnostics.h" +#include "rust-backend.h" +#include "rust-tyty.h" +#include "rust-tyty-visitor.h" +#include "rust-hir-map.h" + +namespace Rust { +namespace Compile { + +class TyTyCompile : public TyTy::TyVisitor +{ +public: + static ::Btype *compile (::Backend *backend, TyTy::TyBase *ty) + { + TyTyCompile compiler (backend); + ty->accept_vis (compiler); + rust_assert (compiler.translated != nullptr); + return compiler.translated; + } + + ~TyTyCompile () {} + + void visit (TyTy::InferType &type) override + { + // there shouldn't be any of these left + gcc_unreachable (); + } + + void visit (TyTy::UnitType &type) override {} + + void visit (TyTy::FnType &type) override + { + Backend::Btyped_identifier receiver; + std::vector<Backend::Btyped_identifier> parameters; + std::vector<Backend::Btyped_identifier> results; + + if (!type.get_return_type ()->is_unit ()) + { + auto hir_type = type.get_return_type (); + auto ret = TyTyCompile::compile (backend, hir_type); + results.push_back (Backend::Btyped_identifier ( + "_", ret, 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 + = TyTyCompile::compile (backend, param_tyty->get_base_type ()); + auto compiled_param = Backend::Btyped_identifier ( + param_tyty->get_identifier (), compiled_param_type, + mappings->lookup_location (param_tyty->get_ref ())); + + parameters.push_back (compiled_param); + } + + translated + = backend->function_type (receiver, parameters, results, NULL, + mappings->lookup_location (type.get_ref ())); + } + + void visit (TyTy::ParamType &type) override {} + + void visit (TyTy::BoolType &type) override + { + translated = backend->named_type ("bool", backend->bool_type (), + Linemap::predeclared_location ()); + } + + void visit (TyTy::IntType &type) override + { + switch (type.get_kind ()) + { + case TyTy::IntType::I8: + translated + = backend->named_type ("i8", backend->integer_type (false, 8), + Linemap::predeclared_location ()); + return; + + case TyTy::IntType::I16: + translated + = backend->named_type ("i16", backend->integer_type (false, 16), + Linemap::predeclared_location ()); + return; + + case TyTy::IntType::I32: + translated + = backend->named_type ("i32", backend->integer_type (false, 32), + Linemap::predeclared_location ()); + return; + } + gcc_unreachable (); + } + + void visit (TyTy::UintType &type) override + { + switch (type.get_kind ()) + { + case TyTy::UintType::U8: + translated = backend->named_type ("i8", backend->integer_type (true, 8), + Linemap::predeclared_location ()); + return; + + case TyTy::UintType::U16: + translated + = backend->named_type ("i16", backend->integer_type (true, 16), + Linemap::predeclared_location ()); + return; + + case TyTy::UintType::U32: + translated + = backend->named_type ("i32", backend->integer_type (true, 32), + Linemap::predeclared_location ()); + return; + } + gcc_unreachable (); + } + +private: + TyTyCompile (::Backend *backend) + : backend (backend), translated (nullptr), + mappings (Analysis::Mappings::get ()) + {} + + ::Backend *backend; + ::Btype *translated; + Analysis::Mappings *mappings; +}; + +class TyTyExtractParamsFromFnType : public TyTy::TyVisitor +{ +public: + static std::vector<TyTy::ParamType *> compile (TyTy::TyBase *ty) + { + TyTyExtractParamsFromFnType compiler; + ty->accept_vis (compiler); + rust_assert (compiler.ok); + return compiler.translated; + } + + ~TyTyExtractParamsFromFnType () {} + + 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<TyTy::ParamType *> 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::FnType &type) override + { + ok = true; + translated = type.get_return_type (); + } + +private: + TyTyExtractRetFromFnType () : ok (false), translated (nullptr) {} + + bool ok; + 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::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 + +#endif // RUST_COMPILE_TYTY diff --git a/gcc/rust/backend/rust-compile-var-decl.h b/gcc/rust/backend/rust-compile-var-decl.h new file mode 100644 index 0000000..be3141a --- /dev/null +++ b/gcc/rust/backend/rust-compile-var-decl.h @@ -0,0 +1,69 @@ +// 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 +// <http://www.gnu.org/licenses/>. + +#ifndef RUST_COMPILE_VAR_DECL +#define RUST_COMPILE_VAR_DECL + +#include "rust-compile-base.h" + +namespace Rust { +namespace Compile { + +class CompileVarDecl : public HIRCompileBase +{ +public: + static ::Bvariable *compile (::Bfunction *fndecl, HIR::Stmt *stmt, + Context *ctx) + { + CompileVarDecl compiler (ctx, fndecl); + stmt->accept_vis (compiler); + rust_assert (compiler.translated != nullptr); + ctx->insert_var_decl (stmt->get_mappings ().get_hirid (), + compiler.translated); + return compiler.translated; + } + + virtual ~CompileVarDecl () {} + + void visit (HIR::LetStmt &stmt) + { + 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 = ctx->get_backend ()->local_variable ( + fndecl, stmt.get_pattern ()->as_string (), translated_type, + NULL /*decl_var*/, false /*address_taken*/, stmt.get_locus ()); + } + +private: + CompileVarDecl (Context *ctx, ::Bfunction *fndecl) + : HIRCompileBase (ctx), fndecl (fndecl), translated (nullptr) + {} + + ::Bfunction *fndecl; + ::Bvariable *translated; +}; + +} // namespace Compile +} // namespace Rust + +#endif // RUST_COMPILE_VAR_DECL diff --git a/gcc/rust/backend/rust-compile.cc b/gcc/rust/backend/rust-compile.cc index a4b5cd4..11c380b 100644 --- a/gcc/rust/backend/rust-compile.cc +++ b/gcc/rust/backend/rust-compile.cc @@ -17,16 +17,31 @@ // <http://www.gnu.org/licenses/>. #include "rust-compile.h" -#include "rust-diagnostics.h" +#include "rust-compile-item.h" namespace Rust { namespace Compile { +CompileCrate::CompileCrate (HIR::Crate &crate, Context *ctx) + : crate (crate), ctx (ctx) +{} + CompileCrate::~CompileCrate () {} void CompileCrate::Compile (HIR::Crate &crate, Context *ctx) -{} + +{ + CompileCrate c (crate, ctx); + c.go (); +} + +void +CompileCrate::go () +{ + for (auto it = crate.items.begin (); it != crate.items.end (); it++) + CompileItem::compile (it->get (), ctx); +} } // namespace Compile } // namespace Rust diff --git a/gcc/rust/backend/rust-compile.h b/gcc/rust/backend/rust-compile.h index 5ee1122..18f3e54 100644 --- a/gcc/rust/backend/rust-compile.h +++ b/gcc/rust/backend/rust-compile.h @@ -20,55 +20,12 @@ #define RUST_COMPILE_H #include "rust-system.h" -#include "rust-hir-map.h" -#include "rust-name-resolver.h" -#include "rust-hir-type-check.h" -#include "rust-linemap.h" -#include "rust-backend.h" +#include "rust-hir-full.h" +#include "rust-compile-context.h" namespace Rust { namespace Compile { -class Context -{ -public: - Context (::Backend *backend) - : backend (backend), resolver (Resolver::Resolver::get ()), - tyctx (Resolver::TypeCheckContext::get ()), - mappings (Analysis::Mappings::get ()) - {} - - ~Context () {} - - ::Backend *get_backend () { return backend; } - Resolver::Resolver *get_resolver () { return resolver; } - Resolver::TypeCheckContext *get_tyctx () { return tyctx; } - Analysis::Mappings *get_mappings () { return mappings; } - - void push_type (::Btype *t) { type_decls.push_back (t); } - void push_var (::Bvariable *v) { var_decls.push_back (v); } - void push_const (::Bexpression *c) { const_decls.push_back (c); } - void push_function (::Bfunction *f) { func_decls.push_back (f); } - - void write_to_backend () - { - backend->write_global_definitions (type_decls, const_decls, func_decls, - var_decls); - } - -private: - ::Backend *backend; - Resolver::Resolver *resolver; - Resolver::TypeCheckContext *tyctx; - Analysis::Mappings *mappings; - - // To GCC middle-end - std::vector< ::Btype *> type_decls; - std::vector< ::Bvariable *> var_decls; - std::vector< ::Bexpression *> const_decls; - std::vector< ::Bfunction *> func_decls; -}; - class CompileCrate { public: @@ -78,6 +35,7 @@ public: private: CompileCrate (HIR::Crate &crate, Context *ctx); + void go (); HIR::Crate &crate; Context *ctx; diff --git a/gcc/rust/hir/rust-ast-lower-item.h b/gcc/rust/hir/rust-ast-lower-item.h index e0ce862..e6c86b8 100644 --- a/gcc/rust/hir/rust-ast-lower-item.h +++ b/gcc/rust/hir/rust-ast-lower-item.h @@ -69,9 +69,16 @@ public: auto translated_type = std::unique_ptr<HIR::Type> ( ASTLoweringType::translate (param.get_type ().get ())); - function_params.push_back ( - HIR::FunctionParam (std::move (translated_pattern), - std::move (translated_type), param.get_locus ())); + auto crate_num = mappings->get_current_crate (); + Analysis::NodeMapping mapping (crate_num, param.get_node_id (), + mappings->get_next_hir_id (crate_num), + UNKNOWN_LOCAL_DEFID); + + auto hir_param + = HIR::FunctionParam (mapping, std::move (translated_pattern), + std::move (translated_type), + param.get_locus ()); + function_params.push_back (hir_param); } std::unique_ptr<HIR::BlockExpr> function_body @@ -83,7 +90,7 @@ public: mappings->get_next_hir_id (crate_num), mappings->get_next_localdef_id (crate_num)); - translated + auto fn = new HIR::Function (mapping, std::move (function_name), std::move (qualifiers), std::move (generic_params), std::move (function_params), std::move (return_type), @@ -92,9 +99,21 @@ public: mappings->insert_defid_mapping (mapping.get_defid (), translated); mappings->insert_hir_item (mapping.get_crate_num (), mapping.get_hirid (), - translated); + fn); mappings->insert_location (crate_num, mapping.get_hirid (), function.get_locus ()); + + // add the mappings for the function params at the end + for (auto ¶m : fn->function_params) + { + mappings->insert_hir_param (mapping.get_crate_num (), + param.get_mappings ()->get_hirid (), + ¶m); + mappings->insert_location (crate_num, mapping.get_hirid (), + param.get_locus ()); + } + + translated = fn; } // Helpers diff --git a/gcc/rust/hir/rust-ast-lower-stmt.h b/gcc/rust/hir/rust-ast-lower-stmt.h index c813639..c57d14f 100644 --- a/gcc/rust/hir/rust-ast-lower-stmt.h +++ b/gcc/rust/hir/rust-ast-lower-stmt.h @@ -60,6 +60,7 @@ public: stmt.get_locus ()); mappings->insert_location (crate_num, mapping.get_hirid (), stmt.get_locus ()); + mappings->insert_hir_stmt (crate_num, mapping.get_hirid (), translated); } void visit (AST::LetStmt &stmt) @@ -86,6 +87,7 @@ public: std::move (outer_attrs), stmt.get_locus ()); mappings->insert_location (crate_num, mapping.get_hirid (), stmt.get_locus ()); + mappings->insert_hir_stmt (crate_num, mapping.get_hirid (), translated); } private: diff --git a/gcc/rust/hir/tree/rust-hir-expr.h b/gcc/rust/hir/tree/rust-hir-expr.h index b08aa91..36c2085 100644 --- a/gcc/rust/hir/tree/rust-hir-expr.h +++ b/gcc/rust/hir/tree/rust-hir-expr.h @@ -536,6 +536,7 @@ public: void accept_vis (HIRVisitor &vis) override; Expr *get_lhs () { return main_or_left_expr.get (); } + Expr *get_rhs () { return right_expr.get (); } /* TODO: implement via a function call to std::cmp::PartialEq::eq(&op1, &op2) * maybe? */ @@ -610,6 +611,8 @@ public: Expr *get_lhs () { return main_or_left_expr.get (); } + Expr *get_rhs () { return right_expr.get (); } + protected: /* Use covariance to implement clone function as returning this object rather * than base */ @@ -2562,6 +2565,14 @@ public: } } + Location get_closing_locus () + { + if (statements.size () == 0) + return get_locus (); + + return statements[statements.size () - 1]->get_locus_slow (); + } + protected: /* Use covariance to implement clone function as returning this object rather * than base */ diff --git a/gcc/rust/hir/tree/rust-hir-item.h b/gcc/rust/hir/tree/rust-hir-item.h index cf24bae..e0477f4 100644 --- a/gcc/rust/hir/tree/rust-hir-item.h +++ b/gcc/rust/hir/tree/rust-hir-item.h @@ -409,17 +409,20 @@ public: std::unique_ptr<Type> type; Location locus; + Analysis::NodeMapping mappings; - FunctionParam (std::unique_ptr<Pattern> param_name, + FunctionParam (Analysis::NodeMapping mappings, + std::unique_ptr<Pattern> param_name, std::unique_ptr<Type> param_type, Location locus) : param_name (std::move (param_name)), type (std::move (param_type)), - locus (locus) + locus (locus), mappings (mappings) {} // Copy constructor uses clone FunctionParam (FunctionParam const &other) : param_name (other.param_name->clone_pattern ()), - type (other.type->clone_type ()), locus (other.locus) + type (other.type->clone_type ()), locus (other.locus), + mappings (other.mappings) {} // Overload assignment operator to use clone @@ -428,6 +431,7 @@ public: param_name = other.param_name->clone_pattern (); type = other.type->clone_type (); locus = other.locus; + mappings = other.mappings; return *this; } @@ -436,15 +440,6 @@ public: FunctionParam (FunctionParam &&other) = default; FunctionParam &operator= (FunctionParam &&other) = default; - // Returns whether FunctionParam is in an invalid state. - bool is_error () const { return param_name == nullptr || type == nullptr; } - - // Creates an error FunctionParam. - static FunctionParam create_error () - { - return FunctionParam (nullptr, nullptr, Location ()); - } - std::string as_string () const; Location get_locus () const { return locus; } @@ -452,6 +447,8 @@ public: Pattern *get_param_name () { return param_name.get (); } Type *get_type () { return type.get (); } + + Analysis::NodeMapping *get_mappings () { return &mappings; } }; // Visibility of item - if the item has it, then it is some form of public @@ -1191,8 +1188,6 @@ public: Location locus; - std::vector<LetStmt *> locals; - std::string as_string () const override; // Returns whether function has generic parameters. diff --git a/gcc/rust/hir/tree/rust-hir-stmt.h b/gcc/rust/hir/tree/rust-hir-stmt.h index 31d55b6..c799b5e 100644 --- a/gcc/rust/hir/tree/rust-hir-stmt.h +++ b/gcc/rust/hir/tree/rust-hir-stmt.h @@ -117,6 +117,8 @@ public: HIR::Expr *get_init_expr () { return init_expr.get (); } + HIR::Pattern *get_pattern () { return variables_pattern.get (); } + protected: /* Use covariance to implement clone function as returning this object rather * than base */ @@ -174,6 +176,8 @@ public: void accept_vis (HIRVisitor &vis) override; + Expr *get_expr () { return expr.get (); } + protected: /* Use covariance to implement clone function as returning this object rather * than base */ diff --git a/gcc/rust/resolve/rust-ast-resolve-expr.h b/gcc/rust/resolve/rust-ast-resolve-expr.h index b9e7f6a..9e98fda 100644 --- a/gcc/rust/resolve/rust-ast-resolve-expr.h +++ b/gcc/rust/resolve/rust-ast-resolve-expr.h @@ -38,7 +38,13 @@ public: void visit (AST::PathInExpression &expr) { - if (resolver->get_name_scope ().lookup (expr.as_string (), &resolved_node)) + if (!resolver->get_name_scope ().lookup (expr.as_string (), &resolved_node)) + { + rust_error_at (expr.get_locus (), "unknown path %s", + expr.as_string ().c_str ()); + return; + } + else { resolver->insert_resolved_name (expr.get_node_id (), resolved_node); resolver->insert_new_definition (expr.get_node_id (), @@ -60,7 +66,7 @@ public: ResolveExpr::go (p, expr.get_node_id ()); return true; }); - /// resolver->insert_resolved_name(NodeId refId,NodeId defId) + // resolver->insert_resolved_name(NodeId refId,NodeId defId) } void visit (AST::AssignmentExpr &expr) diff --git a/gcc/rust/resolve/rust-ast-resolve-pattern.h b/gcc/rust/resolve/rust-ast-resolve-pattern.h index a393d31..fc2da70 100644 --- a/gcc/rust/resolve/rust-ast-resolve-pattern.h +++ b/gcc/rust/resolve/rust-ast-resolve-pattern.h @@ -78,7 +78,6 @@ public: void visit (AST::IdentifierPattern &pattern) { - printf ("declaration for: %s\n", pattern.as_string ().c_str ()); // if we have a duplicate id this then allows for shadowing correctly // as new refs to this decl will match back here so it is ok to overwrite resolver->get_name_scope ().insert (pattern.get_ident (), diff --git a/gcc/rust/resolve/rust-ast-resolve-stmt.h b/gcc/rust/resolve/rust-ast-resolve-stmt.h index 623fbd4..20d40f1 100644 --- a/gcc/rust/resolve/rust-ast-resolve-stmt.h +++ b/gcc/rust/resolve/rust-ast-resolve-stmt.h @@ -39,6 +39,11 @@ public: ~ResolveStmt () {} + void visit (AST::ExprStmtWithoutBlock &stmt) + { + ResolveExpr::go (stmt.get_expr ().get (), stmt.get_node_id ()); + } + void visit (AST::LetStmt &stmt) { PatternDeclaration::go (stmt.get_pattern ().get (), stmt.get_node_id ()); diff --git a/gcc/rust/typecheck/rust-hir-type-check-expr.h b/gcc/rust/typecheck/rust-hir-type-check-expr.h index 2e715e9..32a5d8b 100644 --- a/gcc/rust/typecheck/rust-hir-type-check-expr.h +++ b/gcc/rust/typecheck/rust-hir-type-check-expr.h @@ -110,16 +110,25 @@ public: return; } + // 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 + Definition def; + if (!resolver->lookup_definition (ref_node_id, &def)) + { + rust_error_at (expr.get_locus (), "unknown reference"); + return; + } + // node back to HIR HirId ref; if (!mappings->lookup_node_to_hir (expr.get_mappings ().get_crate_num (), - ref_node_id, &ref)) + def.parent, &ref)) { rust_error_at (expr.get_locus (), "reverse lookup failure"); return; } - // check if this has a type + // the base reference for this name _must_ have a type set TyTy::TyBase *lookup; if (!context->lookup_type (ref, &lookup)) { @@ -138,13 +147,19 @@ public: { switch (expr.get_lit_type ()) { - case HIR::Literal::LitType::INT: - infered = new TyTy::IntType (expr.get_mappings ().get_hirid (), - TyTy::IntType::IntKind::I32); + case HIR::Literal::LitType::INT: { + // FIXME: + // assume i32 let the combiner functions figure it out + // this should look at the suffix of the literal value to check + auto ok = context->lookup_builtin ("i32", &infered); + rust_assert (ok); + } break; - case HIR::Literal::LitType::BOOL: - infered = new TyTy::BoolType (expr.get_mappings ().get_hirid ()); + case HIR::Literal::LitType::BOOL: { + auto ok = context->lookup_builtin ("bool", &infered); + rust_assert (ok); + } break; default: diff --git a/gcc/rust/typecheck/rust-hir-type-check-item.h b/gcc/rust/typecheck/rust-hir-type-check-item.h index 29d6db6..ab964a9 100644 --- a/gcc/rust/typecheck/rust-hir-type-check-item.h +++ b/gcc/rust/typecheck/rust-hir-type-check-item.h @@ -66,6 +66,7 @@ public: rust_error_at (function.locus, "failed to lookup function type"); return; } + // need to get the return type from this ResolveFnType resolve_fn_type (fnType); context->push_return_type (resolve_fn_type.go ()); diff --git a/gcc/rust/typecheck/rust-hir-type-check-stmt.h b/gcc/rust/typecheck/rust-hir-type-check-stmt.h index 39c48f0..ccf1138 100644 --- a/gcc/rust/typecheck/rust-hir-type-check-stmt.h +++ b/gcc/rust/typecheck/rust-hir-type-check-stmt.h @@ -36,6 +36,11 @@ public: stmt->accept_vis (resolver); } + void visit (HIR::ExprStmtWithoutBlock &stmt) + { + TypeCheckExpr::Resolve (stmt.get_expr ()); + } + void visit (HIR::LetStmt &stmt) { TyTy::TyBase *init_expr_ty = nullptr; diff --git a/gcc/rust/typecheck/rust-hir-type-check-toplevel.h b/gcc/rust/typecheck/rust-hir-type-check-toplevel.h index c15aaef..25e6c0b 100644 --- a/gcc/rust/typecheck/rust-hir-type-check-toplevel.h +++ b/gcc/rust/typecheck/rust-hir-type-check-toplevel.h @@ -44,9 +44,18 @@ public: else ret_type = TypeCheckType::Resolve (function.return_type.get ()); - std::vector<TyTy::TyBase *> params; + std::vector<TyTy::ParamType *> params; for (auto ¶m : function.function_params) - params.push_back (TypeCheckType::Resolve (param.type.get ())); + { + // get the name as well required for later on + auto param_type = TypeCheckType::Resolve (param.type.get ()); + auto param_tyty + = new TyTy::ParamType (param.get_mappings ()->get_hirid (), + param.param_name->as_string (), param_type); + params.push_back (param_tyty); + + context->insert_type (param.get_mappings ()->get_hirid (), param_tyty); + } auto fnType = new TyTy::FnType (function.get_mappings ().get_hirid (), params, ret_type); diff --git a/gcc/rust/typecheck/rust-hir-type-check-type.h b/gcc/rust/typecheck/rust-hir-type-check-type.h index d8721a3..beab77a 100644 --- a/gcc/rust/typecheck/rust-hir-type-check-type.h +++ b/gcc/rust/typecheck/rust-hir-type-check-type.h @@ -55,6 +55,7 @@ public: return; } + // reverse lookup the hir node from ast node id HirId hir_lookup; if (context->lookup_type_by_node_id (ref, &hir_lookup)) { @@ -63,7 +64,7 @@ public: return; } - // this might be a struct type reference + // this might be a struct type (TyTy::ADT) reference // TODO printf ("UNREACHABLE %s\n", path.as_string ().c_str ()); gcc_unreachable (); diff --git a/gcc/rust/typecheck/rust-hir-type-check.h b/gcc/rust/typecheck/rust-hir-type-check.h index 5a8abe1..6deecdd 100644 --- a/gcc/rust/typecheck/rust-hir-type-check.h +++ b/gcc/rust/typecheck/rust-hir-type-check.h @@ -33,6 +33,7 @@ public: ~TypeCheckContext (); + bool lookup_builtin (std::string name, TyTy::TyBase **type); void insert_builtin (HirId id, NodeId ref, TyTy::TyBase *type); void insert_type (HirId id, TyTy::TyBase *type); diff --git a/gcc/rust/typecheck/rust-tyctx.cc b/gcc/rust/typecheck/rust-tyctx.cc index 195291e..8869e34 100644 --- a/gcc/rust/typecheck/rust-tyctx.cc +++ b/gcc/rust/typecheck/rust-tyctx.cc @@ -35,11 +35,23 @@ TypeCheckContext::TypeCheckContext () {} TypeCheckContext::~TypeCheckContext () {} +bool +TypeCheckContext::lookup_builtin (std::string name, TyTy::TyBase **type) +{ + for (auto &builtin : builtins) + { + if (name.compare (builtin->as_string ()) == 0) + { + *type = builtin.get (); + return true; + } + } + return false; +} + void TypeCheckContext::insert_builtin (HirId id, NodeId ref, TyTy::TyBase *type) { - printf ("inserting builtin: hir %u node %u -> %s\n", id, ref, - type->as_string ().c_str ()); node_id_refs[ref] = id; resolved[id] = type; builtins.push_back (std::unique_ptr<TyTy::TyBase> (type)); diff --git a/gcc/rust/typecheck/rust-tyty-rules.h b/gcc/rust/typecheck/rust-tyty-rules.h index 375d909..372229b 100644 --- a/gcc/rust/typecheck/rust-tyty-rules.h +++ b/gcc/rust/typecheck/rust-tyty-rules.h @@ -155,8 +155,8 @@ public: TyBase *combine (TyBase *other) { - other->accept_vis (*this); - return resolved; + // we only case about the base type of a param + return base->get_base_type ()->combine (other); } private: diff --git a/gcc/rust/typecheck/rust-tyty.cc b/gcc/rust/typecheck/rust-tyty.cc index 2124408..4a36d4f 100644 --- a/gcc/rust/typecheck/rust-tyty.cc +++ b/gcc/rust/typecheck/rust-tyty.cc @@ -99,7 +99,7 @@ ParamType::accept_vis (TyVisitor &vis) std::string ParamType::as_string () const { - return "(" + type->as_string () + ")"; + return "(" + identifier + " :" + type->as_string () + ")"; } TyBase * diff --git a/gcc/rust/typecheck/rust-tyty.h b/gcc/rust/typecheck/rust-tyty.h index 688643c..4e04490 100644 --- a/gcc/rust/typecheck/rust-tyty.h +++ b/gcc/rust/typecheck/rust-tyty.h @@ -54,12 +54,12 @@ public: virtual void accept_vis (TyVisitor &vis) = 0; - virtual bool is_unit () const { return false; } - virtual std::string as_string () const = 0; virtual TyBase *combine (TyBase *other) = 0; + virtual bool is_unit () const { return kind == TypeKind::UNIT; } + protected: TyBase (HirId ref, TypeKind kind) : kind (kind), ref (ref) {} @@ -95,46 +95,51 @@ public: TyBase *combine (TyBase *other) override; }; -class FnType : public TyBase +class ParamType : public TyBase { public: - FnType (HirId ref, std::vector<TyBase *> params, TyBase *type) - : TyBase (ref, TypeKind::FNDEF), params (params), type (type) + ParamType (HirId ref, std::string identifier, TyBase *type) + : TyBase (ref, TypeKind::PARAM), identifier (identifier), type (type) {} void accept_vis (TyVisitor &vis) override; std::string as_string () const override; - TyBase *return_type () { return type; } - TyBase *combine (TyBase *other) override; - size_t num_params () const { return params.size (); } + std::string get_identifier () const { return identifier; } - TyBase *param_at (size_t idx) { return params[idx]; } - - TyBase *get_return_type () { return type; } + TyBase *get_base_type () { return type; } private: - std::vector<TyBase *> params; + std::string identifier; TyBase *type; }; -class ParamType : public TyBase +class FnType : public TyBase { public: - ParamType (HirId ref, TyBase *type) - : TyBase (ref, TypeKind::PARAM), type (type) + FnType (HirId ref, std::vector<ParamType *> params, TyBase *type) + : TyBase (ref, TypeKind::FNDEF), params (params), type (type) {} void accept_vis (TyVisitor &vis) override; std::string as_string () const override; + TyBase *return_type () { return type; } + TyBase *combine (TyBase *other) override; + size_t num_params () const { return params.size (); } + + ParamType *param_at (size_t idx) { return params[idx]; } + + TyBase *get_return_type () { return type; } + private: + std::vector<ParamType *> params; TyBase *type; }; diff --git a/gcc/rust/util/rust-hir-map.cc b/gcc/rust/util/rust-hir-map.cc index 70c59f3..bdf487e 100644 --- a/gcc/rust/util/rust-hir-map.cc +++ b/gcc/rust/util/rust-hir-map.cc @@ -305,6 +305,55 @@ Mappings::lookup_hir_type (CrateNum crateNum, HirId id) } void +Mappings::insert_hir_stmt (CrateNum crateNum, HirId id, HIR::Stmt *type) +{ + rust_assert (lookup_hir_stmt (crateNum, id) == nullptr); + + hirStmtMappings[crateNum][id] = type; + nodeIdToHirMappings[crateNum][type->get_mappings ().get_nodeid ()] = id; +} + +HIR::Stmt * +Mappings::lookup_hir_stmt (CrateNum crateNum, HirId id) +{ + auto it = hirStmtMappings.find (crateNum); + if (it == hirStmtMappings.end ()) + return nullptr; + + auto iy = it->second.find (id); + if (iy == it->second.end ()) + return nullptr; + + return iy->second; +} + +void +Mappings::insert_hir_param (CrateNum crateNum, HirId id, + HIR::FunctionParam *param) +{ + rust_assert (lookup_hir_stmt (crateNum, id) == nullptr); + + printf ("inserting param with node id %u hir id: %u\n", + param->get_mappings ()->get_nodeid (), id); + hirParamMappings[crateNum][id] = param; + nodeIdToHirMappings[crateNum][param->get_mappings ()->get_nodeid ()] = id; +} + +HIR::FunctionParam * +Mappings::lookup_hir_param (CrateNum crateNum, HirId id) +{ + auto it = hirParamMappings.find (crateNum); + if (it == hirParamMappings.end ()) + return nullptr; + + auto iy = it->second.find (id); + if (iy == it->second.end ()) + return nullptr; + + return iy->second; +} + +void Mappings::insert_local_defid_mapping (CrateNum crateNum, LocalDefId id, HIR::Item *item) { @@ -377,5 +426,22 @@ Mappings::lookup_location (CrateNum crate, HirId id) return iy->second; } +bool +Mappings::resolve_nodeid_to_stmt (CrateNum crate, NodeId id, HIR::Stmt **stmt) +{ + auto it = nodeIdToHirMappings.find (crate); + if (it == nodeIdToHirMappings.end ()) + return false; + + auto iy = it->second.find (id); + if (iy == it->second.end ()) + return false; + + HirId resolved = iy->second; + auto resolved_stmt = lookup_hir_stmt (crate, resolved); + *stmt = resolved_stmt; + return resolved_stmt != nullptr; +} + } // namespace Analysis } // namespace Rust diff --git a/gcc/rust/util/rust-hir-map.h b/gcc/rust/util/rust-hir-map.h index 7fc8777..a400265 100644 --- a/gcc/rust/util/rust-hir-map.h +++ b/gcc/rust/util/rust-hir-map.h @@ -115,6 +115,12 @@ public: void insert_hir_type (CrateNum crateNum, HirId id, HIR::Type *type); HIR::Type *lookup_hir_type (CrateNum crateNum, HirId id); + void insert_hir_stmt (CrateNum crateNum, HirId id, HIR::Stmt *type); + HIR::Stmt *lookup_hir_stmt (CrateNum crateNum, HirId id); + + void insert_hir_param (CrateNum crateNum, HirId id, HIR::FunctionParam *type); + HIR::FunctionParam *lookup_hir_param (CrateNum crateNum, HirId id); + void walk_local_defids_for_crate (CrateNum crateNum, std::function<bool (HIR::Item *)> cb); @@ -127,6 +133,12 @@ public: return lookup_location (get_current_crate (), id); } + bool resolve_nodeid_to_stmt (CrateNum crate, NodeId id, HIR::Stmt **stmt); + bool resolve_nodeid_to_stmt (NodeId id, HIR::Stmt **stmt) + { + return resolve_nodeid_to_stmt (get_current_crate (), id, stmt); + } + private: Mappings (); @@ -145,6 +157,8 @@ private: std::map<CrateNum, std::map<HirId, HIR::Item *> > hirItemMappings; std::map<CrateNum, std::map<HirId, HIR::Type *> > hirTypeMappings; std::map<CrateNum, std::map<HirId, HIR::Expr *> > hirExprMappings; + std::map<CrateNum, std::map<HirId, HIR::Stmt *> > hirStmtMappings; + std::map<CrateNum, std::map<HirId, HIR::FunctionParam *> > hirParamMappings; // location info std::map<CrateNum, std::map<NodeId, Location> > locations; |