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 /gcc | |
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.
Diffstat (limited to 'gcc')
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; |