diff options
Diffstat (limited to 'gcc/rust/backend')
32 files changed, 1915 insertions, 896 deletions
diff --git a/gcc/rust/backend/rust-compile-asm.cc b/gcc/rust/backend/rust-compile-asm.cc new file mode 100644 index 0000000..f04a03e --- /dev/null +++ b/gcc/rust/backend/rust-compile-asm.cc @@ -0,0 +1,199 @@ +#include "rust-compile-asm.h" +#include "rust-compile-expr.h" +#include "rust-system.h" + +namespace Rust { +namespace Compile { + +CompileAsm::CompileAsm (Context *ctx) : HIRCompileBase (ctx) {} + +tree +CompileAsm::tree_codegen_asm (HIR::InlineAsm &expr) +{ + auto asm_expr + = asm_build_stmt (expr.get_locus (), {asm_construct_string_tree (expr), + asm_construct_outputs (expr), + asm_construct_inputs (expr), + asm_construct_clobber_tree (expr), + asm_construct_label_tree (expr)}); + + ASM_INPUT_P (asm_expr) = expr.is_simple_asm (); + ASM_VOLATILE_P (asm_expr) = false; + ASM_INLINE_P (asm_expr) = expr.is_inline_asm (); + /*Backend::debug (asm_expr);*/ + return asm_expr; +} + +tree +CompileAsm::asm_build_stmt ( + location_t loc, + const std::array<tree, CompileAsm::ASM_TREE_ARRAY_LENGTH> &trees) +{ + // Prototype functiion for building an ASM_EXPR tree. + tree ret; + bool side_effects; + + ret = make_node (ASM_EXPR); + TREE_TYPE (ret) = void_type_node; + SET_EXPR_LOCATION (ret, loc); + + /* TREE_SIDE_EFFECTS will already be set for statements with + implicit side effects. Here we make sure it is set for other + expressions by checking whether the parameters have side + effects. */ + + // This is here because of c-typeck.cc's code + // I'm not sure what kind of effects it has + side_effects = false; + for (size_t i = 0; i < trees.size (); i++) + { + tree t = trees[i]; + if (t && !TYPE_P (t)) + side_effects |= TREE_SIDE_EFFECTS (t); + TREE_OPERAND (ret, i) = t; + } + + TREE_SIDE_EFFECTS (ret) |= side_effects; + + return ret; +} + +tree +CompileAsm::asm_construct_string_tree (HIR::InlineAsm &expr) +{ + // To construct an ASM_EXPR tree, we need to build a STRING_CST tree. + // + // We do this by concatenating all the template strings in the InlineAsm + // into one big std::string seperated by tabs and newlines. (For easier + // debugging and reading) + std::stringstream ss; + for (const auto &template_str : expr.template_strs) + ss << template_str.symbol << "\n"; + + std::string result = ss.str (); + return Backend::string_constant_expression (result); +} + +tree +CompileAsm::asm_construct_outputs (HIR::InlineAsm &expr) +{ + // TODO: Do i need to do this? + + tree head = NULL_TREE; + for (auto &output : expr.get_operands ()) + { + if (output.get_register_type () + == AST::InlineAsmOperand::RegisterType::Out) + { + auto out = output.get_out (); + + tree out_tree = CompileExpr::Compile (*out.expr, this->ctx); + // expects a tree list + // TODO: This assumes that the output is a register + std::string expr_name = "=r"; + auto name = build_string (expr_name.size () + 1, expr_name.c_str ()); + head + = chainon (head, build_tree_list (build_tree_list (NULL_TREE, name), + out_tree)); + + /*Backend::debug (head);*/ + /*head = chainon (head, out_tree);*/ + } + } + return head; +} + +tree +CompileAsm::asm_construct_inputs (HIR::InlineAsm &expr) +{ + // TODO: Do i need to do this? + tree head = NULL_TREE; + for (auto &input : expr.get_operands ()) + { + if (input.get_register_type () == AST::InlineAsmOperand::RegisterType::In) + { + auto in = input.get_in (); + + tree in_tree = CompileExpr::Compile (*in.expr, this->ctx); + // expects a tree list + // TODO: This assumes that the input is a register + std::string expr_name = "r"; + auto name = build_string (expr_name.size () + 1, expr_name.c_str ()); + head + = chainon (head, build_tree_list (build_tree_list (NULL_TREE, name), + in_tree)); + + /*head = chainon (head, out_tree);*/ + } + } + return head; +} + +tree +CompileAsm::asm_construct_clobber_tree (HIR::InlineAsm &expr) +{ + // TODO: Do i need to do this? + return NULL_TREE; +} + +tree +CompileAsm::asm_construct_label_tree (HIR::InlineAsm &expr) +{ + // TODO: Do i need to do this? + return NULL_TREE; +} + +CompileLlvmAsm::CompileLlvmAsm (Context *ctx) : HIRCompileBase (ctx) {} + +tree +CompileLlvmAsm::construct_operands (std::vector<HIR::LlvmOperand> operands) +{ + tree head = NULL_TREE; + for (auto &operand : operands) + { + tree t = CompileExpr::Compile (*operand.expr, this->ctx); + auto name = build_string (operand.constraint.size () + 1, + operand.constraint.c_str ()); + head = chainon (head, + build_tree_list (build_tree_list (NULL_TREE, name), t)); + } + return head; +} + +tree +CompileLlvmAsm::construct_clobbers (std::vector<AST::TupleClobber> clobbers) +{ + tree head = NULL_TREE; + for (auto &clobber : clobbers) + { + auto name + = build_string (clobber.symbol.size () + 1, clobber.symbol.c_str ()); + head = chainon (head, build_tree_list (NULL_TREE, name)); + } + return head; +} + +tree +CompileLlvmAsm::tree_codegen_asm (HIR::LlvmInlineAsm &expr) +{ + tree ret = make_node (ASM_EXPR); + TREE_TYPE (ret) = void_type_node; + SET_EXPR_LOCATION (ret, expr.get_locus ()); + ASM_VOLATILE_P (ret) = expr.options.is_volatile; + + std::stringstream ss; + for (const auto &template_str : expr.templates) + { + ss << template_str.symbol << "\n"; + } + + ASM_STRING (ret) = Backend::string_constant_expression (ss.str ()); + ASM_INPUTS (ret) = construct_operands (expr.inputs); + ASM_OUTPUTS (ret) = construct_operands (expr.outputs); + ASM_CLOBBERS (ret) = construct_clobbers (expr.get_clobbers ()); + + return ret; +} + +} // namespace Compile +} // namespace Rust diff --git a/gcc/rust/backend/rust-compile-asm.h b/gcc/rust/backend/rust-compile-asm.h new file mode 100644 index 0000000..22be94a --- /dev/null +++ b/gcc/rust/backend/rust-compile-asm.h @@ -0,0 +1,75 @@ +// Copyright (C) 2020-2024 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_ASM +#define RUST_COMPILE_ASM + +#include "rust-compile-base.h" +#include "rust-hir-visitor.h" + +namespace Rust { +namespace Compile { + +class CompileAsm : private HIRCompileBase +{ +private: + // RELEVANT MEMBER FUNCTIONS + + // The limit is 5 because it stands for the 5 things that the C version of + // build_asm_expr accepts: string, output, input, clobber and label. + // The function signature is + // + // tree + // build_asm_expr (location_t loc, tree string, tree outputs, tree inputs, + // tree clobbers, tree labels, bool simple, bool is_inline) + static const int ASM_TREE_ARRAY_LENGTH = 5; + tree asm_build_stmt (location_t, + const std::array<tree, ASM_TREE_ARRAY_LENGTH> &); + + tree asm_construct_string_tree (HIR::InlineAsm &); + tree asm_construct_outputs (HIR::InlineAsm &); + tree asm_construct_inputs (HIR::InlineAsm &); + tree asm_construct_clobber_tree (HIR::InlineAsm &); + tree asm_construct_label_tree (HIR::InlineAsm &); + +public: + // WE WILL OPEN THIS UP WHEN WE WANT TO ADD A DEDICATED PASS OF HIR'S ASM + // translation. + // static tree Compile (HIR::Expr *expr, Context *ctx); + + CompileAsm (Context *ctx); + + tree tree_codegen_asm (HIR::InlineAsm &); +}; + +class CompileLlvmAsm : private HIRCompileBase +{ +private: + tree construct_operands (std::vector<HIR::LlvmOperand> operands); + + tree construct_clobbers (std::vector<AST::TupleClobber>); + +public: + CompileLlvmAsm (Context *ctx); + + tree tree_codegen_asm (HIR::LlvmInlineAsm &); +}; + +} // namespace Compile +} // namespace Rust +#endif // RUST_COMPILE_ASM diff --git a/gcc/rust/backend/rust-compile-base.cc b/gcc/rust/backend/rust-compile-base.cc index 584d6a0..f4b578d 100644 --- a/gcc/rust/backend/rust-compile-base.cc +++ b/gcc/rust/backend/rust-compile-base.cc @@ -25,7 +25,8 @@ #include "rust-compile-type.h" #include "rust-constexpr.h" #include "rust-diagnostics.h" -#include "rust-expr.h" // for AST::AttrInputLiteral +#include "rust-expr.h" // for AST::AttrInputLiteral +#include "rust-hir-map.h" #include "rust-macro.h" // for AST::MetaNameValueStr #include "rust-hir-path-probe.h" #include "rust-type-util.h" @@ -39,6 +40,9 @@ #include "tree.h" #include "print-tree.h" +// rust-name-resolution-2.0 +#include "options.h" + namespace Rust { namespace Compile { @@ -545,7 +549,7 @@ HIRCompileBase::mark_addressable (tree exp, location_t locus) } tree -HIRCompileBase::address_expression (tree expr, location_t location) +HIRCompileBase::address_expression (tree expr, location_t location, tree ptrty) { if (expr == error_mark_node) return error_mark_node; @@ -553,7 +557,22 @@ HIRCompileBase::address_expression (tree expr, location_t location) if (!mark_addressable (expr, location)) return error_mark_node; - return build_fold_addr_expr_loc (location, expr); + if (ptrty == NULL || ptrty == error_mark_node) + ptrty = build_pointer_type (TREE_TYPE (expr)); + + return build_fold_addr_expr_with_type_loc (location, expr, ptrty); +} + +tree +HIRCompileBase::compile_constant_expr ( + Context *ctx, HirId coercion_id, TyTy::BaseType *resolved_type, + TyTy::BaseType *expected_type, const Resolver::CanonicalPath &canonical_path, + HIR::Expr &const_value_expr, location_t locus, location_t expr_locus) +{ + HIRCompileBase c (ctx); + return c.compile_constant_item (coercion_id, resolved_type, expected_type, + canonical_path, const_value_expr, locus, + expr_locus); } tree @@ -582,8 +601,9 @@ HIRCompileBase::compile_function_body (tree fndecl, if (function_body.has_expr ()) { - location_t locus = function_body.get_final_expr ()->get_locus (); - tree return_value = CompileExpr::Compile (function_body.expr.get (), ctx); + location_t locus = function_body.get_final_expr ().get_locus (); + tree return_value + = CompileExpr::Compile (function_body.get_final_expr (), ctx); // we can only return this if non unit value return type if (!fn_return_ty->is_unit ()) @@ -611,7 +631,7 @@ HIRCompileBase::compile_function_body (tree fndecl, ctx->add_statement (return_value); // now just return unit expression - tree unit_expr = unit_expression (ctx, locus); + tree unit_expr = unit_expression (locus); tree return_stmt = Backend::return_statement (fndecl, unit_expr, locus); ctx->add_statement (return_stmt); @@ -622,7 +642,7 @@ HIRCompileBase::compile_function_body (tree fndecl, // we can only do this if the function is of unit type otherwise other // errors should have occurred location_t locus = function_body.get_locus (); - tree return_value = unit_expression (ctx, locus); + tree return_value = unit_expression (locus); tree return_stmt = Backend::return_statement (fndecl, return_value, locus); ctx->add_statement (return_stmt); @@ -646,18 +666,19 @@ get_abi (const AST::AttrVec &outer_attrs, tree HIRCompileBase::compile_function ( - const std::string &fn_name, HIR::SelfParam &self_param, + bool is_root_item, const std::string &fn_name, + tl::optional<HIR::SelfParam> &self_param, std::vector<HIR::FunctionParam> &function_params, const HIR::FunctionQualifiers &qualifiers, HIR::Visibility &visibility, AST::AttrVec &outer_attrs, location_t locus, HIR::BlockExpr *function_body, - const Resolver::CanonicalPath *canonical_path, TyTy::FnType *fntype) + const Resolver::CanonicalPath &canonical_path, TyTy::FnType *fntype) { tree compiled_fn_type = TyTyResolveCompile::compile (ctx, fntype); std::string ir_symbol_name - = canonical_path->get () + fntype->subst_as_string (); + = canonical_path.get () + fntype->subst_as_string (); // we don't mangle the main fn since we haven't implemented the main shim - bool is_main_fn = fn_name.compare ("main") == 0; + bool is_main_fn = fn_name.compare ("main") == 0 && is_root_item; if (is_main_fn) { rust_assert (!main_identifier_node); @@ -666,6 +687,11 @@ HIRCompileBase::compile_function ( } std::string asm_name = fn_name; + auto &mappings = Analysis::Mappings::get (); + + if (flag_name_resolution_2_0) + ir_symbol_name = mappings.get_current_crate_name () + "::" + ir_symbol_name; + unsigned int flags = 0; tree fndecl = Backend::function (compiled_fn_type, ir_symbol_name, "" /* asm_name */, flags, locus); @@ -677,7 +703,7 @@ HIRCompileBase::compile_function ( // conditionally mangle the function name bool should_mangle = should_mangle_item (fndecl); if (!is_main_fn && should_mangle) - asm_name = ctx->mangle_item (fntype, *canonical_path); + asm_name = ctx->mangle_item (fntype, canonical_path); SET_DECL_ASSEMBLER_NAME (fndecl, get_identifier_with_length (asm_name.data (), asm_name.length ())); @@ -688,39 +714,39 @@ HIRCompileBase::compile_function ( // setup the params TyTy::BaseType *tyret = fntype->get_return_type (); std::vector<Bvariable *> param_vars; - if (!self_param.is_error ()) + if (self_param) { rust_assert (fntype->is_method ()); TyTy::BaseType *self_tyty_lookup = fntype->get_self_type (); tree self_type = TyTyResolveCompile::compile (ctx, self_tyty_lookup); Bvariable *compiled_self_param - = CompileSelfParam::compile (ctx, fndecl, self_param, self_type, - self_param.get_locus ()); + = CompileSelfParam::compile (ctx, fndecl, self_param.value (), + self_type, self_param->get_locus ()); param_vars.push_back (compiled_self_param); - ctx->insert_var_decl (self_param.get_mappings ().get_hirid (), + ctx->insert_var_decl (self_param->get_mappings ().get_hirid (), compiled_self_param); } // offset from + 1 for the TyTy::FnType being used when this is a method to // skip over Self on the FnType - bool is_method = !self_param.is_error (); + bool is_method = self_param.has_value (); size_t i = is_method ? 1 : 0; for (auto &referenced_param : function_params) { - auto tyty_param = fntype->param_at (i++); - auto param_tyty = tyty_param.second; + auto &tyty_param = fntype->param_at (i++); + auto param_tyty = tyty_param.get_type (); auto compiled_param_type = TyTyResolveCompile::compile (ctx, param_tyty); location_t param_locus = referenced_param.get_locus (); Bvariable *compiled_param_var - = CompileFnParam::compile (ctx, fndecl, &referenced_param, + = CompileFnParam::compile (ctx, fndecl, referenced_param, compiled_param_type, param_locus); param_vars.push_back (compiled_param_var); - const HIR::Pattern ¶m_pattern = *referenced_param.get_param_name (); + const HIR::Pattern ¶m_pattern = referenced_param.get_param_name (); ctx->insert_var_decl (param_pattern.get_mappings ().get_hirid (), compiled_param_var); } @@ -767,15 +793,20 @@ HIRCompileBase::compile_function ( tree HIRCompileBase::compile_constant_item ( - TyTy::BaseType *resolved_type, const Resolver::CanonicalPath *canonical_path, - HIR::Expr *const_value_expr, location_t locus) + HirId coercion_id, TyTy::BaseType *resolved_type, + TyTy::BaseType *expected_type, const Resolver::CanonicalPath &canonical_path, + HIR::Expr &const_value_expr, location_t locus, location_t expr_locus) { - const std::string &ident = canonical_path->get (); + const std::string &ident = canonical_path.get (); tree type = TyTyResolveCompile::compile (ctx, resolved_type); tree const_type = build_qualified_type (type, TYPE_QUAL_CONST); + + tree actual_type = TyTyResolveCompile::compile (ctx, expected_type); + tree actual_const_type = build_qualified_type (actual_type, TYPE_QUAL_CONST); + bool is_block_expr - = const_value_expr->get_expression_type () == HIR::Expr::ExprType::Block; + = const_value_expr.get_expression_type () == HIR::Expr::ExprType::Block; // in order to compile a block expr we want to reuse as much existing // machineary that we already have. This means the best approach is to @@ -789,14 +820,14 @@ HIRCompileBase::compile_constant_item ( TREE_READONLY (fndecl) = 1; tree enclosing_scope = NULL_TREE; - location_t start_location = const_value_expr->get_locus (); - location_t end_location = const_value_expr->get_locus (); + location_t start_location = const_value_expr.get_locus (); + location_t end_location = const_value_expr.get_locus (); if (is_block_expr) { - HIR::BlockExpr *function_body - = static_cast<HIR::BlockExpr *> (const_value_expr); - start_location = function_body->get_locus (); - end_location = function_body->get_end_locus (); + HIR::BlockExpr &function_body + = static_cast<HIR::BlockExpr &> (const_value_expr); + start_location = function_body.get_locus (); + end_location = function_body.get_end_locus (); } tree code_block = Backend::block (fndecl, enclosing_scope, {} /*locals*/, @@ -814,9 +845,9 @@ HIRCompileBase::compile_constant_item ( if (is_block_expr) { - HIR::BlockExpr *function_body - = static_cast<HIR::BlockExpr *> (const_value_expr); - compile_function_body (fndecl, *function_body, resolved_type); + HIR::BlockExpr &function_body + = static_cast<HIR::BlockExpr &> (const_value_expr); + compile_function_body (fndecl, function_body, resolved_type); } else { @@ -824,7 +855,7 @@ HIRCompileBase::compile_constant_item ( tree return_expr = Backend::return_statement (fndecl, value, - const_value_expr->get_locus ()); + const_value_expr.get_locus ()); ctx->add_statement (return_expr); } @@ -841,7 +872,11 @@ HIRCompileBase::compile_constant_item ( tree call = build_call_array_loc (locus, const_type, fndecl, 0, NULL); tree folded_expr = fold_expr (call); - return named_constant_expression (const_type, ident, folded_expr, locus); + // coercion site + tree coerced = coercion_site (coercion_id, folded_expr, resolved_type, + expected_type, locus, expr_locus); + + return named_constant_expression (actual_const_type, ident, coerced, locus); } tree @@ -877,19 +912,18 @@ HIRCompileBase::resolve_method_address (TyTy::FnType *fntype, // Now we can try and resolve the address since this might be a forward // declared function, generic function which has not be compiled yet or // its an not yet trait bound function - HIR::Item *resolved_item = ctx->get_mappings ()->lookup_defid (id); - if (resolved_item != nullptr) + if (auto resolved_item = ctx->get_mappings ().lookup_defid (id)) { if (!fntype->has_substitutions_defined ()) - return CompileItem::compile (resolved_item, ctx); + return CompileItem::compile (*resolved_item, ctx); - return CompileItem::compile (resolved_item, ctx, fntype); + return CompileItem::compile (*resolved_item, ctx, fntype); } // it might be resolved to a trait item HIR::TraitItem *trait_item - = ctx->get_mappings ()->lookup_trait_item_defid (id); - HIR::Trait *trait = ctx->get_mappings ()->lookup_trait_item_mapping ( + = ctx->get_mappings ().lookup_trait_item_defid (id).value (); + HIR::Trait *trait = ctx->get_mappings ().lookup_trait_item_mapping ( trait_item->get_mappings ().get_hirid ()); Resolver::TraitReference *trait_ref @@ -991,7 +1025,7 @@ HIRCompileBase::resolve_method_address (TyTy::FnType *fntype, } tree -HIRCompileBase::unit_expression (Context *ctx, location_t locus) +HIRCompileBase::unit_expression (location_t locus) { tree unit_type = TyTyResolveCompile::get_unit_type (ctx); return Backend::constructor_expression (unit_type, false, {}, -1, locus); diff --git a/gcc/rust/backend/rust-compile-base.h b/gcc/rust/backend/rust-compile-base.h index c581658..65dc350 100644 --- a/gcc/rust/backend/rust-compile-base.h +++ b/gcc/rust/backend/rust-compile-base.h @@ -29,7 +29,14 @@ class HIRCompileBase public: virtual ~HIRCompileBase () {} - static tree address_expression (tree expr, location_t locus); + static tree address_expression (tree expr, location_t locus, + tree ptrty = NULL_TREE); + + static tree compile_constant_expr ( + Context *ctx, HirId coercion_id, TyTy::BaseType *resolved_type, + TyTy::BaseType *expected_type, + const Resolver::CanonicalPath &canonical_path, HIR::Expr &const_value_expr, + location_t locus, location_t expr_locus); protected: HIRCompileBase (Context *ctx) : ctx (ctx) {} @@ -90,19 +97,22 @@ protected: void compile_function_body (tree fndecl, HIR::BlockExpr &function_body, TyTy::BaseType *fn_return_ty); - tree compile_constant_item (TyTy::BaseType *resolved_type, - const Resolver::CanonicalPath *canonical_path, - HIR::Expr *const_value_expr, location_t locus); + tree compile_constant_item (HirId coercion_id, TyTy::BaseType *resolved_type, + TyTy::BaseType *expected_type, + const Resolver::CanonicalPath &canonical_path, + HIR::Expr &const_value_expr, location_t locus, + location_t expr_locus); - tree compile_function (const std::string &fn_name, HIR::SelfParam &self_param, + tree compile_function (bool is_root_item, const std::string &fn_name, + tl::optional<HIR::SelfParam> &self_param, std::vector<HIR::FunctionParam> &function_params, const HIR::FunctionQualifiers &qualifiers, HIR::Visibility &visibility, AST::AttrVec &outer_attrs, location_t locus, HIR::BlockExpr *function_body, - const Resolver::CanonicalPath *canonical_path, + const Resolver::CanonicalPath &canonical_path, TyTy::FnType *fntype); - static tree unit_expression (Context *ctx, location_t locus); + tree unit_expression (location_t locus); void setup_fndecl (tree fndecl, bool is_main_entry_point, bool is_generic_fn, HIR::Visibility &visibility, diff --git a/gcc/rust/backend/rust-compile-block.cc b/gcc/rust/backend/rust-compile-block.cc index 10a7099..b55fe68 100644 --- a/gcc/rust/backend/rust-compile-block.cc +++ b/gcc/rust/backend/rust-compile-block.cc @@ -19,6 +19,7 @@ #include "rust-compile-block.h" #include "rust-compile-stmt.h" #include "rust-compile-expr.h" +#include "rust-hir-expr.h" namespace Rust { namespace Compile { @@ -28,10 +29,10 @@ CompileBlock::CompileBlock (Context *ctx, Bvariable *result) {} tree -CompileBlock::compile (HIR::BlockExpr *expr, Context *ctx, Bvariable *result) +CompileBlock::compile (HIR::BlockExpr &expr, Context *ctx, Bvariable *result) { CompileBlock compiler (ctx, result); - compiler.visit (*expr); + compiler.visit (expr); return compiler.translated; } @@ -60,10 +61,10 @@ CompileBlock::visit (HIR::BlockExpr &expr) if (expr.has_expr ()) { - tree compiled_expr = CompileExpr::Compile (expr.expr.get (), ctx); + tree compiled_expr = CompileExpr::Compile (expr.get_final_expr (), ctx); if (result != nullptr) { - location_t locus = expr.get_final_expr ()->get_locus (); + location_t locus = expr.get_final_expr ().get_locus (); tree result_reference = Backend::var_expression (result, locus); tree assignment @@ -75,7 +76,7 @@ CompileBlock::visit (HIR::BlockExpr &expr) else if (result != nullptr) { location_t locus = expr.get_locus (); - tree compiled_expr = unit_expression (ctx, expr.get_locus ()); + tree compiled_expr = unit_expression (expr.get_locus ()); tree result_reference = Backend::var_expression (result, locus); tree assignment @@ -93,10 +94,8 @@ CompileConditionalBlocks::visit (HIR::IfExpr &expr) { fncontext fnctx = ctx->peek_fn (); tree fndecl = fnctx.fndecl; - tree condition_expr - = CompileExpr::Compile (expr.get_if_condition ().get (), ctx); - tree then_block - = CompileBlock::compile (expr.get_if_block ().get (), ctx, result); + tree condition_expr = CompileExpr::Compile (expr.get_if_condition (), ctx); + tree then_block = CompileBlock::compile (expr.get_if_block (), ctx, result); translated = Backend::if_statement (fndecl, condition_expr, then_block, NULL, expr.get_locus ()); @@ -107,23 +106,20 @@ CompileConditionalBlocks::visit (HIR::IfExprConseqElse &expr) { fncontext fnctx = ctx->peek_fn (); tree fndecl = fnctx.fndecl; - tree condition_expr - = CompileExpr::Compile (expr.get_if_condition ().get (), ctx); - tree then_block - = CompileBlock::compile (expr.get_if_block ().get (), ctx, result); + tree condition_expr = CompileExpr::Compile (expr.get_if_condition (), ctx); + tree then_block = CompileBlock::compile (expr.get_if_block (), ctx, result); // else block std::vector<Bvariable *> locals; - location_t start_location = expr.get_else_block ()->get_locus (); - location_t end_location = expr.get_else_block ()->get_locus (); // FIXME + location_t start_location = expr.get_else_block ().get_locus (); + location_t end_location = expr.get_else_block ().get_locus (); // FIXME tree enclosing_scope = ctx->peek_enclosing_scope (); tree else_block = Backend::block (fndecl, enclosing_scope, locals, start_location, end_location); ctx->push_block (else_block); tree else_stmt_decl - = CompileExprWithBlock::compile (expr.get_else_block ().get (), ctx, - result); + = CompileExprWithBlock::compile (&expr.get_else_block (), ctx, result); ctx->add_statement (else_stmt_decl); diff --git a/gcc/rust/backend/rust-compile-block.h b/gcc/rust/backend/rust-compile-block.h index 52cf057..e288bd8 100644 --- a/gcc/rust/backend/rust-compile-block.h +++ b/gcc/rust/backend/rust-compile-block.h @@ -28,7 +28,7 @@ namespace Compile { class CompileBlock : private HIRCompileBase { public: - static tree compile (HIR::BlockExpr *expr, Context *ctx, Bvariable *result); + static tree compile (HIR::BlockExpr &expr, Context *ctx, Bvariable *result); protected: void visit (HIR::BlockExpr &expr); @@ -83,6 +83,8 @@ public: void visit (HIR::MethodCallExpr &) override {} void visit (HIR::FieldAccessExpr &) override {} void visit (HIR::BlockExpr &) override {} + void visit (HIR::AnonConst &) override {} + void visit (HIR::ConstBlock &) override {} void visit (HIR::ContinueExpr &) override {} void visit (HIR::BreakExpr &) override {} void visit (HIR::RangeFromToExpr &) override {} @@ -96,11 +98,11 @@ public: void visit (HIR::LoopExpr &) override {} void visit (HIR::WhileLoopExpr &) override {} void visit (HIR::WhileLetLoopExpr &) override {} - void visit (HIR::IfLetExpr &) override {} - void visit (HIR::IfLetExprConseqElse &) override {} void visit (HIR::MatchExpr &) override {} void visit (HIR::AwaitExpr &) override {} void visit (HIR::AsyncBlockExpr &) override {} + void visit (HIR::InlineAsm &) override {} + void visit (HIR::LlvmInlineAsm &) override {} private: CompileConditionalBlocks (Context *ctx, Bvariable *result) @@ -135,7 +137,13 @@ public: void visit (HIR::BlockExpr &expr) override { - translated = CompileBlock::compile (&expr, ctx, result); + translated = CompileBlock::compile (expr, ctx, result); + } + + void visit (HIR::ConstBlock &expr) override + { + rust_unreachable (); + // translated = CompileExpr::compile (expr, ctx, result); } // Empty visit for unused Expression HIR nodes. @@ -179,11 +187,12 @@ public: void visit (HIR::LoopExpr &) override {} void visit (HIR::WhileLoopExpr &) override {} void visit (HIR::WhileLetLoopExpr &) override {} - void visit (HIR::IfLetExpr &) override {} - void visit (HIR::IfLetExprConseqElse &) override {} void visit (HIR::MatchExpr &) override {} void visit (HIR::AwaitExpr &) override {} void visit (HIR::AsyncBlockExpr &) override {} + void visit (HIR::InlineAsm &) override {} + void visit (HIR::LlvmInlineAsm &) override {} + void visit (HIR::AnonConst &) override {} private: CompileExprWithBlock (Context *ctx, Bvariable *result) diff --git a/gcc/rust/backend/rust-compile-context.cc b/gcc/rust/backend/rust-compile-context.cc index e9d44f9..b4c544e 100644 --- a/gcc/rust/backend/rust-compile-context.cc +++ b/gcc/rust/backend/rust-compile-context.cc @@ -33,19 +33,8 @@ Context::Context () void Context::setup_builtins () { - auto builtins = resolver->get_builtin_types (); - for (auto it = builtins.begin (); it != builtins.end (); it++) - { - HirId ref; - bool ok = tyctx->lookup_type_by_node_id ((*it)->get_node_id (), &ref); - rust_assert (ok); - - TyTy::BaseType *lookup; - ok = tyctx->lookup_type (ref, &lookup); - rust_assert (ok); - - TyTyResolveCompile::compile (this, lookup); - } + for (auto &builtin : tyctx->get_builtins ()) + TyTyResolveCompile::compile (this, builtin.get ()); } hashval_t diff --git a/gcc/rust/backend/rust-compile-context.h b/gcc/rust/backend/rust-compile-context.h index 671aee1..22e6e19 100644 --- a/gcc/rust/backend/rust-compile-context.h +++ b/gcc/rust/backend/rust-compile-context.h @@ -72,7 +72,10 @@ public: return it->second; compiled_type_map.insert ({h, type}); - push_type (type); + + if (TYPE_NAME (type) != NULL) + push_type (type); + return type; } @@ -89,7 +92,7 @@ public: Resolver::Resolver *get_resolver () { return resolver; } Resolver::TypeCheckContext *get_tyctx () { return tyctx; } - Analysis::Mappings *get_mappings () { return mappings; } + Analysis::Mappings &get_mappings () { return mappings; } void push_block (tree scope) { @@ -390,7 +393,7 @@ public: private: Resolver::Resolver *resolver; Resolver::TypeCheckContext *tyctx; - Analysis::Mappings *mappings; + Analysis::Mappings &mappings; Mangler mangler; // state diff --git a/gcc/rust/backend/rust-compile-expr.cc b/gcc/rust/backend/rust-compile-expr.cc index b5b88b4..0f63310 100644 --- a/gcc/rust/backend/rust-compile-expr.cc +++ b/gcc/rust/backend/rust-compile-expr.cc @@ -25,11 +25,14 @@ #include "rust-constexpr.h" #include "rust-compile-type.h" #include "rust-gcc.h" - +#include "rust-compile-asm.h" #include "fold-const.h" #include "realmpfr.h" #include "convert.h" #include "print-tree.h" +#include "rust-hir-expr.h" +#include "rust-system.h" +#include "rust-tyty.h" namespace Rust { namespace Compile { @@ -39,24 +42,24 @@ CompileExpr::CompileExpr (Context *ctx) {} tree -CompileExpr::Compile (HIR::Expr *expr, Context *ctx) +CompileExpr::Compile (HIR::Expr &expr, Context *ctx) { CompileExpr compiler (ctx); - expr->accept_vis (compiler); + expr.accept_vis (compiler); return compiler.translated; } void CompileExpr::visit (HIR::TupleIndexExpr &expr) { - HIR::Expr *tuple_expr = expr.get_tuple_expr ().get (); + HIR::Expr &tuple_expr = expr.get_tuple_expr (); TupleIndex index = expr.get_tuple_index (); tree receiver_ref = CompileExpr::Compile (tuple_expr, ctx); TyTy::BaseType *tuple_expr_ty = nullptr; bool ok - = ctx->get_tyctx ()->lookup_type (tuple_expr->get_mappings ().get_hirid (), + = ctx->get_tyctx ()->lookup_type (tuple_expr.get_mappings ().get_hirid (), &tuple_expr_ty); rust_assert (ok); @@ -76,7 +79,7 @@ CompileExpr::visit (HIR::TupleExpr &expr) { if (expr.is_unit ()) { - translated = unit_expression (ctx, expr.get_locus ()); + translated = unit_expression (expr.get_locus ()); return; } @@ -96,7 +99,7 @@ CompileExpr::visit (HIR::TupleExpr &expr) std::vector<tree> vals; for (auto &elem : expr.get_tuple_elems ()) { - auto e = CompileExpr::Compile (elem.get (), ctx); + auto e = CompileExpr::Compile (*elem, ctx); vals.push_back (e); } @@ -110,8 +113,8 @@ CompileExpr::visit (HIR::ReturnExpr &expr) auto fncontext = ctx->peek_fn (); tree return_value = expr.has_return_expr () - ? CompileExpr::Compile (expr.return_expr.get (), ctx) - : unit_expression (ctx, expr.get_locus ()); + ? CompileExpr::Compile (expr.get_expr (), ctx) + : unit_expression (expr.get_locus ()); if (expr.has_return_expr ()) { @@ -120,7 +123,7 @@ CompileExpr::visit (HIR::ReturnExpr &expr) TyTy::BaseType *expected = fncontext.retty; location_t lvalue_locus - = ctx->get_mappings ()->lookup_location (expected->get_ref ()); + = ctx->get_mappings ().lookup_location (expected->get_ref ()); TyTy::BaseType *actual = nullptr; bool ok = ctx->get_tyctx ()->lookup_type ( @@ -140,8 +143,8 @@ void CompileExpr::visit (HIR::ArithmeticOrLogicalExpr &expr) { auto op = expr.get_expr_type (); - auto lhs = CompileExpr::Compile (expr.get_lhs ().get (), ctx); - auto rhs = CompileExpr::Compile (expr.get_rhs ().get (), ctx); + auto lhs = CompileExpr::Compile (expr.get_lhs (), ctx); + auto rhs = CompileExpr::Compile (expr.get_rhs (), ctx); // this might be an operator overload situation lets check TyTy::FnType *fntype; @@ -151,41 +154,42 @@ CompileExpr::visit (HIR::ArithmeticOrLogicalExpr &expr) { auto lang_item_type = LangItem::OperatorToLangItem (expr.get_expr_type ()); - translated = resolve_operator_overload (lang_item_type, expr, lhs, rhs, - expr.get_lhs ().get (), - expr.get_rhs ().get ()); + translated = resolve_operator_overload ( + lang_item_type, expr, lhs, rhs, expr.get_lhs (), + tl::optional<std::reference_wrapper<HIR::Expr>> (expr.get_rhs ())); return; } - if (ctx->in_fn () && !ctx->const_context_p ()) - { - auto receiver_tmp = NULL_TREE; - auto receiver - = Backend::temporary_variable (ctx->peek_fn ().fndecl, NULL_TREE, - TREE_TYPE (lhs), lhs, true, - expr.get_locus (), &receiver_tmp); - auto check - = Backend::arithmetic_or_logical_expression_checked (op, lhs, rhs, - expr.get_locus (), - receiver); - - ctx->add_statement (check); - translated = receiver->get_tree (expr.get_locus ()); - } - else + bool can_generate_overflow_checks + = (ctx->in_fn () && !ctx->const_context_p ()) && flag_overflow_checks; + if (!can_generate_overflow_checks) { translated = Backend::arithmetic_or_logical_expression (op, lhs, rhs, expr.get_locus ()); + return; } + + auto receiver_tmp = NULL_TREE; + auto receiver + = Backend::temporary_variable (ctx->peek_fn ().fndecl, NULL_TREE, + TREE_TYPE (lhs), lhs, true, + expr.get_locus (), &receiver_tmp); + auto check + = Backend::arithmetic_or_logical_expression_checked (op, lhs, rhs, + expr.get_locus (), + receiver); + + ctx->add_statement (check); + translated = receiver->get_tree (expr.get_locus ()); } void CompileExpr::visit (HIR::CompoundAssignmentExpr &expr) { auto op = expr.get_expr_type (); - auto lhs = CompileExpr::Compile (expr.get_lhs ().get (), ctx); - auto rhs = CompileExpr::Compile (expr.get_rhs ().get (), ctx); + auto lhs = CompileExpr::Compile (expr.get_lhs (), ctx); + auto rhs = CompileExpr::Compile (expr.get_rhs (), ctx); // this might be an operator overload situation lets check TyTy::FnType *fntype; @@ -197,8 +201,7 @@ CompileExpr::visit (HIR::CompoundAssignmentExpr &expr) expr.get_expr_type ()); auto compound_assignment = resolve_operator_overload (lang_item_type, expr, lhs, rhs, - expr.get_lhs ().get (), - expr.get_rhs ().get ()); + expr.get_lhs (), expr.get_rhs ()); ctx->add_statement (compound_assignment); return; @@ -234,7 +237,25 @@ void CompileExpr::visit (HIR::NegationExpr &expr) { auto op = expr.get_expr_type (); - auto negated_expr = CompileExpr::Compile (expr.get_expr ().get (), ctx); + + auto &literal_expr = expr.get_expr (); + + // If it's a negated integer/float literal, we can return early + if (op == NegationOperator::NEGATE + && literal_expr.get_expression_type () == HIR::Expr::ExprType::Lit) + { + auto &new_literal_expr = static_cast<HIR::LiteralExpr &> (literal_expr); + auto lit_type = new_literal_expr.get_lit_type (); + if (lit_type == HIR::Literal::LitType::INT + || lit_type == HIR::Literal::LitType::FLOAT) + { + new_literal_expr.set_negative (); + translated = CompileExpr::Compile (literal_expr, ctx); + return; + } + } + + auto negated_expr = CompileExpr::Compile (literal_expr, ctx); auto location = expr.get_locus (); // this might be an operator overload situation lets check @@ -246,7 +267,7 @@ CompileExpr::visit (HIR::NegationExpr &expr) auto lang_item_type = LangItem::NegationOperatorToLangItem (op); translated = resolve_operator_overload (lang_item_type, expr, negated_expr, - nullptr, expr.get_expr ().get (), nullptr); + nullptr, expr.get_expr (), tl::nullopt); return; } @@ -257,10 +278,30 @@ void CompileExpr::visit (HIR::ComparisonExpr &expr) { auto op = expr.get_expr_type (); - auto lhs = CompileExpr::Compile (expr.get_lhs ().get (), ctx); - auto rhs = CompileExpr::Compile (expr.get_rhs ().get (), ctx); + auto lhs = CompileExpr::Compile (expr.get_lhs (), ctx); + auto rhs = CompileExpr::Compile (expr.get_rhs (), ctx); auto location = expr.get_locus (); + // this might be an operator overload situation lets check + TyTy::FnType *fntype; + bool is_op_overload = ctx->get_tyctx ()->lookup_operator_overload ( + expr.get_mappings ().get_hirid (), &fntype); + if (is_op_overload) + { + auto seg_name = LangItem::ComparisonToSegment (expr.get_expr_type ()); + auto segment = HIR::PathIdentSegment (seg_name); + auto lang_item_type + = LangItem::ComparisonToLangItem (expr.get_expr_type ()); + + rhs = address_expression (rhs, EXPR_LOCATION (rhs)); + + translated = resolve_operator_overload ( + lang_item_type, expr, lhs, rhs, expr.get_lhs (), + tl::optional<std::reference_wrapper<HIR::Expr>> (expr.get_rhs ()), + segment); + return; + } + translated = Backend::comparison_expression (op, lhs, rhs, location); } @@ -268,8 +309,8 @@ void CompileExpr::visit (HIR::LazyBooleanExpr &expr) { auto op = expr.get_expr_type (); - auto lhs = CompileExpr::Compile (expr.get_lhs ().get (), ctx); - auto rhs = CompileExpr::Compile (expr.get_rhs ().get (), ctx); + auto lhs = CompileExpr::Compile (expr.get_lhs (), ctx); + auto rhs = CompileExpr::Compile (expr.get_rhs (), ctx); auto location = expr.get_locus (); translated = Backend::lazy_boolean_expression (op, lhs, rhs, location); @@ -288,14 +329,14 @@ CompileExpr::visit (HIR::TypeCastExpr &expr) TyTy::BaseType *casted_tyty = nullptr; if (!ctx->get_tyctx ()->lookup_type ( - expr.get_casted_expr ()->get_mappings ().get_hirid (), &casted_tyty)) + expr.get_casted_expr ().get_mappings ().get_hirid (), &casted_tyty)) { translated = error_mark_node; return; } auto type_to_cast_to = TyTyResolveCompile::compile (ctx, type_to_cast_to_ty); - auto casted_expr = CompileExpr::Compile (expr.get_casted_expr ().get (), ctx); + auto casted_expr = CompileExpr::Compile (expr.get_casted_expr (), ctx); std::vector<Resolver::Adjustment> *adjustments = nullptr; bool ok = ctx->get_tyctx ()->lookup_cast_autoderef_mappings ( @@ -318,6 +359,23 @@ CompileExpr::visit (HIR::IfExpr &expr) } void +CompileExpr::visit (HIR::InlineAsm &expr) +{ + CompileAsm asm_codegen (ctx); + ctx->add_statement (asm_codegen.tree_codegen_asm (expr)); + // translated = build_asm_expr (0, NULL_TREE, NULL_TREE, NULL_TREE, NULL_TREE, + // NULL_TREE, true, true); + // CompileAsm::asm_build_expr (expr); +} + +void +CompileExpr::visit (HIR::LlvmInlineAsm &expr) +{ + CompileLlvmAsm asm_codegen (ctx); + ctx->add_statement (asm_codegen.tree_codegen_asm (expr)); +} + +void CompileExpr::visit (HIR::IfExprConseqElse &expr) { TyTy::BaseType *if_type = nullptr; @@ -376,7 +434,7 @@ CompileExpr::visit (HIR::BlockExpr &expr) &ret_var_stmt); ctx->add_statement (ret_var_stmt); - auto block_stmt = CompileBlock::compile (&expr, ctx, tmp); + auto block_stmt = CompileBlock::compile (expr, ctx, tmp); rust_assert (TREE_CODE (block_stmt) == BIND_EXPR); ctx->add_statement (block_stmt); @@ -384,9 +442,21 @@ CompileExpr::visit (HIR::BlockExpr &expr) } void +CompileExpr::visit (HIR::AnonConst &expr) +{ + expr.get_inner_expr ().accept_vis (*this); +} + +void +CompileExpr::visit (HIR::ConstBlock &expr) +{ + expr.get_const_expr ().accept_vis (*this); +} + +void CompileExpr::visit (HIR::UnsafeBlockExpr &expr) { - expr.get_block_expr ()->accept_vis (*this); + expr.get_block_expr ().accept_vis (*this); } void @@ -401,7 +471,7 @@ CompileExpr::visit (HIR::StructExprStruct &struct_expr) } rust_assert (tyty->is_unit ()); - translated = unit_expression (ctx, struct_expr.get_locus ()); + translated = unit_expression (struct_expr.get_locus ()); } void @@ -456,9 +526,9 @@ CompileExpr::visit (HIR::StructExprStructFields &struct_expr) // process arguments auto &argument = struct_expr.get_fields ().at (0); auto lvalue_locus - = ctx->get_mappings ()->lookup_location (expected->get_ty_ref ()); + = ctx->get_mappings ().lookup_location (expected->get_ty_ref ()); auto rvalue_locus = argument->get_locus (); - auto rvalue = CompileStructExprField::Compile (argument.get (), ctx); + auto rvalue = CompileStructExprField::Compile (*argument, ctx); TyTy::BaseType *actual = nullptr; bool ok = ctx->get_tyctx ()->lookup_type ( @@ -488,9 +558,9 @@ CompileExpr::visit (HIR::StructExprStructFields &struct_expr) // process arguments auto &argument = struct_expr.get_fields ().at (i); auto lvalue_locus - = ctx->get_mappings ()->lookup_location (expected->get_ty_ref ()); + = ctx->get_mappings ().lookup_location (expected->get_ty_ref ()); auto rvalue_locus = argument->get_locus (); - auto rvalue = CompileStructExprField::Compile (argument.get (), ctx); + auto rvalue = CompileStructExprField::Compile (*argument, ctx); TyTy::BaseType *actual = nullptr; bool ok = ctx->get_tyctx ()->lookup_type ( @@ -510,45 +580,53 @@ CompileExpr::visit (HIR::StructExprStructFields &struct_expr) } } - // the constructor depends on whether this is actually an enum or not if - // its an enum we need to setup the discriminator - std::vector<tree> ctor_arguments; - if (adt->is_enum ()) + if (!adt->is_enum ()) { - HIR::Expr *discrim_expr = variant->get_discriminant (); - tree discrim_expr_node = CompileExpr::Compile (discrim_expr, ctx); - tree folded_discrim_expr = fold_expr (discrim_expr_node); - tree qualifier = folded_discrim_expr; - - ctor_arguments.push_back (qualifier); + translated + = Backend::constructor_expression (compiled_adt_type, adt->is_enum (), + arguments, union_disriminator, + struct_expr.get_locus ()); + return; } - for (auto &arg : arguments) - ctor_arguments.push_back (arg); + + HIR::Expr &discrim_expr = variant->get_discriminant (); + tree discrim_expr_node = CompileExpr::Compile (discrim_expr, ctx); + tree folded_discrim_expr = fold_expr (discrim_expr_node); + tree qualifier = folded_discrim_expr; + + tree enum_root_files = TYPE_FIELDS (compiled_adt_type); + tree payload_root = DECL_CHAIN (enum_root_files); + + tree payload = Backend::constructor_expression (TREE_TYPE (payload_root), + adt->is_enum (), arguments, + union_disriminator, + struct_expr.get_locus ()); + + std::vector<tree> ctor_arguments = {qualifier, payload}; translated - = Backend::constructor_expression (compiled_adt_type, adt->is_enum (), - ctor_arguments, union_disriminator, + = Backend::constructor_expression (compiled_adt_type, 0, ctor_arguments, -1, struct_expr.get_locus ()); } void CompileExpr::visit (HIR::GroupedExpr &expr) { - translated = CompileExpr::Compile (expr.get_expr_in_parens ().get (), ctx); + translated = CompileExpr::Compile (expr.get_expr_in_parens (), ctx); } void CompileExpr::visit (HIR::FieldAccessExpr &expr) { - HIR::Expr *receiver_expr = expr.get_receiver_expr ().get (); + HIR::Expr &receiver_expr = expr.get_receiver_expr (); tree receiver_ref = CompileExpr::Compile (receiver_expr, ctx); // resolve the receiver back to ADT type TyTy::BaseType *receiver = nullptr; if (!ctx->get_tyctx ()->lookup_type ( - expr.get_receiver_expr ()->get_mappings ().get_hirid (), &receiver)) + expr.get_receiver_expr ().get_mappings ().get_hirid (), &receiver)) { - rust_error_at (expr.get_receiver_expr ()->get_locus (), + rust_error_at (expr.get_receiver_expr ().get_locus (), "unresolved type for receiver"); return; } @@ -643,7 +721,7 @@ CompileExpr::visit (HIR::LoopExpr &expr) ctx->push_loop_begin_label (loop_begin_label); tree code_block - = CompileBlock::compile (expr.get_loop_block ().get (), ctx, nullptr); + = CompileBlock::compile (expr.get_loop_block (), ctx, nullptr); tree loop_expr = Backend::loop_expression (code_block, expr.get_locus ()); ctx->add_statement (loop_expr); @@ -670,8 +748,8 @@ CompileExpr::visit (HIR::WhileLoopExpr &expr) } std::vector<Bvariable *> locals; - location_t start_location = expr.get_loop_block ()->get_locus (); - location_t end_location = expr.get_loop_block ()->get_locus (); // FIXME + location_t start_location = expr.get_loop_block ().get_locus (); + location_t end_location = expr.get_loop_block ().get_locus (); // FIXME tree enclosing_scope = ctx->peek_enclosing_scope (); tree loop_block = Backend::block (fnctx.fndecl, enclosing_scope, locals, @@ -684,15 +762,14 @@ CompileExpr::visit (HIR::WhileLoopExpr &expr) ctx->add_statement (loop_begin_label_decl); ctx->push_loop_begin_label (loop_begin_label); - tree condition - = CompileExpr::Compile (expr.get_predicate_expr ().get (), ctx); + tree condition = CompileExpr::Compile (expr.get_predicate_expr (), ctx); tree exit_condition = fold_build1_loc (expr.get_locus (), TRUTH_NOT_EXPR, boolean_type_node, condition); tree exit_expr = Backend::exit_expression (exit_condition, expr.get_locus ()); ctx->add_statement (exit_expr); tree code_block_stmt - = CompileBlock::compile (expr.get_loop_block ().get (), ctx, nullptr); + = CompileBlock::compile (expr.get_loop_block (), ctx, nullptr); rust_assert (TREE_CODE (code_block_stmt) == BIND_EXPR); ctx->add_statement (code_block_stmt); @@ -708,12 +785,12 @@ CompileExpr::visit (HIR::BreakExpr &expr) { if (expr.has_break_expr ()) { - tree compiled_expr = CompileExpr::Compile (expr.get_expr ().get (), ctx); + tree compiled_expr = CompileExpr::Compile (expr.get_expr (), ctx); Bvariable *loop_result_holder = ctx->peek_loop_context (); tree result_reference = Backend::var_expression (loop_result_holder, - expr.get_expr ()->get_locus ()); + expr.get_expr ().get_locus ()); tree assignment = Backend::assignment_statement (result_reference, compiled_expr, @@ -724,8 +801,24 @@ CompileExpr::visit (HIR::BreakExpr &expr) if (expr.has_label ()) { NodeId resolved_node_id = UNKNOWN_NODEID; - if (!ctx->get_resolver ()->lookup_resolved_label ( - expr.get_label ().get_mappings ().get_nodeid (), &resolved_node_id)) + if (flag_name_resolution_2_0) + { + auto &nr_ctx + = Resolver2_0::ImmutableNameResolutionContext::get ().resolver (); + + if (auto id + = nr_ctx.lookup (expr.get_label ().get_mappings ().get_nodeid ())) + resolved_node_id = *id; + } + else + { + NodeId tmp = UNKNOWN_NODEID; + if (ctx->get_resolver ()->lookup_resolved_label ( + expr.get_label ().get_mappings ().get_nodeid (), &tmp)) + resolved_node_id = tmp; + } + + if (resolved_node_id == UNKNOWN_NODEID) { rust_error_at ( expr.get_label ().get_locus (), @@ -734,12 +827,14 @@ CompileExpr::visit (HIR::BreakExpr &expr) return; } - HirId ref = UNKNOWN_HIRID; - if (!ctx->get_mappings ()->lookup_node_to_hir (resolved_node_id, &ref)) + tl::optional<HirId> hid + = ctx->get_mappings ().lookup_node_to_hir (resolved_node_id); + if (!hid.has_value ()) { rust_fatal_error (expr.get_locus (), "reverse lookup label failure"); return; } + auto ref = hid.value (); tree label = NULL_TREE; if (!ctx->lookup_label_decl (ref, &label)) @@ -768,8 +863,25 @@ CompileExpr::visit (HIR::ContinueExpr &expr) if (expr.has_label ()) { NodeId resolved_node_id = UNKNOWN_NODEID; - if (!ctx->get_resolver ()->lookup_resolved_label ( - expr.get_label ().get_mappings ().get_nodeid (), &resolved_node_id)) + if (flag_name_resolution_2_0) + { + auto &nr_ctx + = Resolver2_0::ImmutableNameResolutionContext::get ().resolver (); + + if (auto id + = nr_ctx.lookup (expr.get_label ().get_mappings ().get_nodeid ())) + resolved_node_id = *id; + } + else + { + NodeId tmp = UNKNOWN_NODEID; + + if (ctx->get_resolver ()->lookup_resolved_label ( + expr.get_label ().get_mappings ().get_nodeid (), &tmp)) + resolved_node_id = tmp; + } + + if (resolved_node_id == UNKNOWN_NODEID) { rust_error_at ( expr.get_label ().get_locus (), @@ -778,12 +890,14 @@ CompileExpr::visit (HIR::ContinueExpr &expr) return; } - HirId ref = UNKNOWN_HIRID; - if (!ctx->get_mappings ()->lookup_node_to_hir (resolved_node_id, &ref)) + tl::optional<HirId> hid + = ctx->get_mappings ().lookup_node_to_hir (resolved_node_id); + if (!hid.has_value ()) { rust_fatal_error (expr.get_locus (), "reverse lookup label failure"); return; } + auto ref = hid.value (); if (!ctx->lookup_label_decl (ref, &label)) { @@ -799,7 +913,7 @@ CompileExpr::visit (HIR::ContinueExpr &expr) void CompileExpr::visit (HIR::BorrowExpr &expr) { - tree main_expr = CompileExpr::Compile (expr.get_expr ().get (), ctx); + tree main_expr = CompileExpr::Compile (expr.get_expr (), ctx); if (RS_DST_FLAG_P (TREE_TYPE (main_expr))) { translated = main_expr; @@ -811,7 +925,8 @@ CompileExpr::visit (HIR::BorrowExpr &expr) &tyty)) return; - translated = address_expression (main_expr, expr.get_locus ()); + tree expected_type = TyTyResolveCompile::compile (ctx, tyty); + translated = address_expression (main_expr, expr.get_locus (), expected_type); } void @@ -826,7 +941,7 @@ CompileExpr::visit (HIR::DereferenceExpr &expr) return; } - tree main_expr = CompileExpr::Compile (expr.get_expr ().get (), ctx); + tree main_expr = CompileExpr::Compile (expr.get_expr (), ctx); // this might be an operator overload situation lets check TyTy::FnType *fntype; @@ -837,7 +952,7 @@ CompileExpr::visit (HIR::DereferenceExpr &expr) auto lang_item_type = LangItem::Kind::DEREF; tree operator_overload_call = resolve_operator_overload (lang_item_type, expr, main_expr, nullptr, - expr.get_expr ().get (), nullptr); + expr.get_expr (), tl::nullopt); // rust deref always returns a reference from this overload then we can // actually do the indirection @@ -897,8 +1012,8 @@ CompileExpr::visit (HIR::LiteralExpr &expr) void CompileExpr::visit (HIR::AssignmentExpr &expr) { - auto lvalue = CompileExpr::Compile (expr.get_lhs ().get (), ctx); - auto rvalue = CompileExpr::Compile (expr.get_rhs ().get (), ctx); + auto lvalue = CompileExpr::Compile (expr.get_lhs (), ctx); + auto rvalue = CompileExpr::Compile (expr.get_rhs (), ctx); // assignments are coercion sites so lets convert the rvalue if necessary TyTy::BaseType *expected = nullptr; @@ -906,16 +1021,16 @@ CompileExpr::visit (HIR::AssignmentExpr &expr) bool ok; ok = ctx->get_tyctx ()->lookup_type ( - expr.get_lhs ()->get_mappings ().get_hirid (), &expected); + expr.get_lhs ().get_mappings ().get_hirid (), &expected); rust_assert (ok); ok = ctx->get_tyctx ()->lookup_type ( - expr.get_rhs ()->get_mappings ().get_hirid (), &actual); + expr.get_rhs ().get_mappings ().get_hirid (), &actual); rust_assert (ok); rvalue = coercion_site (expr.get_mappings ().get_hirid (), rvalue, actual, - expected, expr.get_lhs ()->get_locus (), - expr.get_rhs ()->get_locus ()); + expected, expr.get_lhs ().get_locus (), + expr.get_rhs ().get_locus ()); // rust_debug_loc (expr.get_locus (), "XXXXXX assignment"); // debug_tree (rvalue); @@ -936,28 +1051,15 @@ check_match_scrutinee (HIR::MatchExpr &expr, Context *ctx) { TyTy::BaseType *scrutinee_expr_tyty = nullptr; if (!ctx->get_tyctx ()->lookup_type ( - expr.get_scrutinee_expr ()->get_mappings ().get_hirid (), + expr.get_scrutinee_expr ().get_mappings ().get_hirid (), &scrutinee_expr_tyty)) { return TyTy::TypeKind::ERROR; } TyTy::TypeKind scrutinee_kind = scrutinee_expr_tyty->get_kind (); - rust_assert ((TyTy::is_primitive_type_kind (scrutinee_kind) - && scrutinee_kind != TyTy::TypeKind::NEVER) - || scrutinee_kind == TyTy::TypeKind::ADT - || scrutinee_kind == TyTy::TypeKind::TUPLE - || scrutinee_kind == TyTy::TypeKind::REF); - if (scrutinee_kind == TyTy::TypeKind::ADT) - { - // this will need to change but for now the first pass implementation, - // lets assert this is the case - TyTy::ADTType *adt = static_cast<TyTy::ADTType *> (scrutinee_expr_tyty); - rust_assert (adt->is_enum ()); - rust_assert (adt->number_of_variants () > 0); - } - else if (scrutinee_kind == TyTy::TypeKind::FLOAT) + if (scrutinee_kind == TyTy::TypeKind::FLOAT) { // FIXME: CASE_LABEL_EXPR does not support floating point types. // Find another way to compile these. @@ -998,6 +1100,15 @@ CompileExpr::visit (HIR::MatchExpr &expr) return; } + // if the result of this expression is meant to be never type then we can + // optimise this away but there is the case where match arms resolve to ! + // because of return statements we need to special case this + if (!expr.has_match_arms () && expr_tyty->is<TyTy::NeverType> ()) + { + translated = unit_expression (expr.get_locus ()); + return; + } + fncontext fnctx = ctx->peek_fn (); Bvariable *tmp = NULL; tree enclosing_scope = ctx->peek_enclosing_scope (); @@ -1012,7 +1123,7 @@ CompileExpr::visit (HIR::MatchExpr &expr) // lets compile the scrutinee expression tree match_scrutinee_rval - = CompileExpr::Compile (expr.get_scrutinee_expr ().get (), ctx); + = CompileExpr::Compile (expr.get_scrutinee_expr (), ctx); Bvariable *match_scrutinee_tmp_var = Backend::temporary_variable (fnctx.fndecl, enclosing_scope, @@ -1022,7 +1133,7 @@ CompileExpr::visit (HIR::MatchExpr &expr) ctx->add_statement (ret_var_stmt); tree match_scrutinee_expr = match_scrutinee_tmp_var->get_tree ( - expr.get_scrutinee_expr ()->get_locus ()); + expr.get_scrutinee_expr ().get_locus ()); tree assignment = Backend::assignment_statement (match_scrutinee_expr, match_scrutinee_rval, @@ -1055,17 +1166,27 @@ CompileExpr::visit (HIR::MatchExpr &expr) ctx->push_block (arm_body_block); // setup the bindings for the block - CompilePatternBindings::Compile (kase_pattern.get (), - match_scrutinee_expr, ctx); + CompilePatternBindings::Compile (*kase_pattern, match_scrutinee_expr, + ctx); // compile the expr and setup the assignment if required when tmp != // NULL location_t arm_locus = kase_arm.get_locus (); - tree kase_expr_tree - = CompileExpr::Compile (kase.get_expr ().get (), ctx); + tree kase_expr_tree = CompileExpr::Compile (kase.get_expr (), ctx); tree result_reference = Backend::var_expression (tmp, arm_locus); + + TyTy::BaseType *actual = nullptr; + bool ok = ctx->get_tyctx ()->lookup_type ( + kase.get_expr ().get_mappings ().get_hirid (), &actual); + rust_assert (ok); + + tree coerced_result + = coercion_site (kase.get_expr ().get_mappings ().get_hirid (), + kase_expr_tree, actual, expr_tyty, + expr.get_locus (), arm_locus); + tree assignment - = Backend::assignment_statement (result_reference, kase_expr_tree, + = Backend::assignment_statement (result_reference, coerced_result, arm_locus); ctx->add_statement (assignment); @@ -1077,7 +1198,7 @@ CompileExpr::visit (HIR::MatchExpr &expr) ctx->pop_block (); tree check_expr - = CompilePatternCheckExpr::Compile (kase_pattern.get (), + = CompilePatternCheckExpr::Compile (*kase_pattern, match_scrutinee_expr, ctx); tree check_stmt @@ -1099,7 +1220,7 @@ CompileExpr::visit (HIR::CallExpr &expr) { TyTy::BaseType *tyty = nullptr; if (!ctx->get_tyctx ()->lookup_type ( - expr.get_fnexpr ()->get_mappings ().get_hirid (), &tyty)) + expr.get_fnexpr ().get_mappings ().get_hirid (), &tyty)) { rust_error_at (expr.get_locus (), "unknown type"); return; @@ -1125,7 +1246,7 @@ CompileExpr::visit (HIR::CallExpr &expr) { HirId variant_id; bool ok = ctx->get_tyctx ()->lookup_variant_definition ( - expr.get_fnexpr ()->get_mappings ().get_hirid (), &variant_id); + expr.get_fnexpr ().get_mappings ().get_hirid (), &variant_id); rust_assert (ok); ok = adt->lookup_variant_by_id (variant_id, &variant, @@ -1136,10 +1257,10 @@ CompileExpr::visit (HIR::CallExpr &expr) // this assumes all fields are in order from type resolution and if a // base struct was specified those fields are filed via accessors std::vector<tree> arguments; - for (size_t i = 0; i < expr.get_arguments ().size (); i++) + for (size_t i = 0; i < expr.num_params (); i++) { auto &argument = expr.get_arguments ().at (i); - auto rvalue = CompileExpr::Compile (argument.get (), ctx); + auto rvalue = CompileExpr::Compile (*argument, ctx); // assignments are coercion sites so lets convert the rvalue if // necessary @@ -1153,7 +1274,7 @@ CompileExpr::visit (HIR::CallExpr &expr) // coerce it if required location_t lvalue_locus - = ctx->get_mappings ()->lookup_location (expected->get_ty_ref ()); + = ctx->get_mappings ().lookup_location (expected->get_ty_ref ()); location_t rvalue_locus = argument->get_locus (); rvalue = coercion_site (argument->get_mappings ().get_hirid (), rvalue, @@ -1163,26 +1284,34 @@ CompileExpr::visit (HIR::CallExpr &expr) arguments.push_back (rvalue); } - // the constructor depends on whether this is actually an enum or not if - // its an enum we need to setup the discriminator - std::vector<tree> ctor_arguments; - if (adt->is_enum ()) + if (!adt->is_enum ()) { - HIR::Expr *discrim_expr = variant->get_discriminant (); - tree discrim_expr_node = CompileExpr::Compile (discrim_expr, ctx); - tree folded_discrim_expr = fold_expr (discrim_expr_node); - tree qualifier = folded_discrim_expr; - - ctor_arguments.push_back (qualifier); + translated + = Backend::constructor_expression (compiled_adt_type, + adt->is_enum (), arguments, + union_disriminator, + expr.get_locus ()); + return; } - for (auto &arg : arguments) - ctor_arguments.push_back (arg); - translated - = Backend::constructor_expression (compiled_adt_type, adt->is_enum (), - ctor_arguments, union_disriminator, + HIR::Expr &discrim_expr = variant->get_discriminant (); + tree discrim_expr_node = CompileExpr::Compile (discrim_expr, ctx); + tree folded_discrim_expr = fold_expr (discrim_expr_node); + tree qualifier = folded_discrim_expr; + + tree enum_root_files = TYPE_FIELDS (compiled_adt_type); + tree payload_root = DECL_CHAIN (enum_root_files); + + tree payload + = Backend::constructor_expression (TREE_TYPE (payload_root), true, + {arguments}, union_disriminator, expr.get_locus ()); + std::vector<tree> ctor_arguments = {qualifier, payload}; + translated = Backend::constructor_expression (compiled_adt_type, false, + ctor_arguments, -1, + expr.get_locus ()); + return; } @@ -1202,13 +1331,13 @@ CompileExpr::visit (HIR::CallExpr &expr) } const TyTy::FnType *fn = static_cast<const TyTy::FnType *> (base); - auto param = fn->param_at (index); - *result = param.second; + auto ¶m = fn->param_at (index); + *result = param.get_type (); return true; }; - auto fn_address = CompileExpr::Compile (expr.get_fnexpr ().get (), ctx); + auto fn_address = CompileExpr::Compile (expr.get_fnexpr (), ctx); // is this a closure call? bool possible_trait_call @@ -1235,7 +1364,7 @@ CompileExpr::visit (HIR::CallExpr &expr) for (size_t i = 0; i < expr.get_arguments ().size (); i++) { auto &argument = expr.get_arguments ().at (i); - auto rvalue = CompileExpr::Compile (argument.get (), ctx); + auto rvalue = CompileExpr::Compile (*argument, ctx); if (is_variadic && i >= required_num_args) { @@ -1257,7 +1386,7 @@ CompileExpr::visit (HIR::CallExpr &expr) // coerce it if required location_t lvalue_locus - = ctx->get_mappings ()->lookup_location (expected->get_ty_ref ()); + = ctx->get_mappings ().lookup_location (expected->get_ty_ref ()); location_t rvalue_locus = argument->get_locus (); rvalue = coercion_site (argument->get_mappings ().get_hirid (), rvalue, actual, expected, lvalue_locus, rvalue_locus); @@ -1275,7 +1404,7 @@ void CompileExpr::visit (HIR::MethodCallExpr &expr) { // method receiver - tree self = CompileExpr::Compile (expr.get_receiver ().get (), ctx); + tree self = CompileExpr::Compile (expr.get_receiver (), ctx); // lookup the expected function type TyTy::BaseType *lookup_fntype = nullptr; @@ -1286,8 +1415,8 @@ CompileExpr::visit (HIR::MethodCallExpr &expr) TyTy::FnType *fntype = static_cast<TyTy::FnType *> (lookup_fntype); TyTy::BaseType *receiver = nullptr; - ok = ctx->get_tyctx ()->lookup_receiver (expr.get_mappings ().get_hirid (), - &receiver); + ok = ctx->get_tyctx ()->lookup_type ( + expr.get_receiver ().get_mappings ().get_hirid (), &receiver); rust_assert (ok); bool is_dyn_dispatch @@ -1315,7 +1444,7 @@ CompileExpr::visit (HIR::MethodCallExpr &expr) // lookup the autoderef mappings HirId autoderef_mappings_id - = expr.get_receiver ()->get_mappings ().get_hirid (); + = expr.get_receiver ().get_mappings ().get_hirid (); std::vector<Resolver::Adjustment> *adjustments = nullptr; ok = ctx->get_tyctx ()->lookup_autoderef_mappings (autoderef_mappings_id, &adjustments); @@ -1323,7 +1452,7 @@ CompileExpr::visit (HIR::MethodCallExpr &expr) // apply adjustments for the fn call self = resolve_adjustements (*adjustments, self, - expr.get_receiver ()->get_locus ()); + expr.get_receiver ().get_locus ()); std::vector<tree> args; args.push_back (self); // adjusted self @@ -1332,12 +1461,12 @@ CompileExpr::visit (HIR::MethodCallExpr &expr) for (size_t i = 0; i < expr.get_arguments ().size (); i++) { auto &argument = expr.get_arguments ().at (i); - auto rvalue = CompileExpr::Compile (argument.get (), ctx); + auto rvalue = CompileExpr::Compile (*argument, ctx); // assignments are coercion sites so lets convert the rvalue if // necessary, offset from the already adjusted implicit self bool ok; - TyTy::BaseType *expected = fntype->param_at (i + 1).second; + TyTy::BaseType *expected = fntype->param_at (i + 1).get_type (); TyTy::BaseType *actual = nullptr; ok = ctx->get_tyctx ()->lookup_type ( @@ -1346,7 +1475,7 @@ CompileExpr::visit (HIR::MethodCallExpr &expr) // coerce it if required location_t lvalue_locus - = ctx->get_mappings ()->lookup_location (expected->get_ty_ref ()); + = ctx->get_mappings ().lookup_location (expected->get_ty_ref ()); location_t rvalue_locus = argument->get_locus (); rvalue = coercion_site (argument->get_mappings ().get_hirid (), rvalue, actual, expected, lvalue_locus, rvalue_locus); @@ -1412,10 +1541,10 @@ CompileExpr::get_receiver_from_dyn (const TyTy::DynamicObjectType *dyn, } tree -CompileExpr::resolve_operator_overload (LangItem::Kind lang_item_type, - HIR::OperatorExprMeta expr, tree lhs, - tree rhs, HIR::Expr *lhs_expr, - HIR::Expr *rhs_expr) +CompileExpr::resolve_operator_overload ( + LangItem::Kind lang_item_type, HIR::OperatorExprMeta expr, tree lhs, tree rhs, + HIR::Expr &lhs_expr, tl::optional<std::reference_wrapper<HIR::Expr>> rhs_expr, + HIR::PathIdentSegment specified_segment) { TyTy::FnType *fntype; bool is_op_overload = ctx->get_tyctx ()->lookup_operator_overload ( @@ -1424,8 +1553,8 @@ CompileExpr::resolve_operator_overload (LangItem::Kind lang_item_type, TyTy::BaseType *receiver = nullptr; bool ok - = ctx->get_tyctx ()->lookup_receiver (expr.get_mappings ().get_hirid (), - &receiver); + = ctx->get_tyctx ()->lookup_type (lhs_expr.get_mappings ().get_hirid (), + &receiver); rust_assert (ok); bool is_generic_receiver = receiver->get_kind () == TyTy::TypeKind::PARAM; @@ -1436,7 +1565,10 @@ CompileExpr::resolve_operator_overload (LangItem::Kind lang_item_type, } // lookup compiled functions since it may have already been compiled - HIR::PathIdentSegment segment_name (LangItem::ToString (lang_item_type)); + HIR::PathIdentSegment segment_name + = specified_segment.is_error () + ? HIR::PathIdentSegment (LangItem::ToString (lang_item_type)) + : specified_segment; tree fn_expr = resolve_method_address (fntype, receiver, expr.get_locus ()); // lookup the autoderef mappings @@ -1446,7 +1578,7 @@ CompileExpr::resolve_operator_overload (LangItem::Kind lang_item_type, rust_assert (ok); // apply adjustments for the fn call - tree self = resolve_adjustements (*adjustments, lhs, lhs_expr->get_locus ()); + tree self = resolve_adjustements (*adjustments, lhs, lhs_expr.get_locus ()); std::vector<tree> args; args.push_back (self); // adjusted self @@ -1489,6 +1621,10 @@ CompileExpr::compile_integer_literal (const HIR::LiteralExpr &expr, mpz_init (type_max); get_type_static_bounds (type, type_min, type_max); + if (expr.is_negative ()) + { + mpz_neg (ival, ival); + } if (mpz_cmp (ival, type_min) < 0 || mpz_cmp (ival, type_max) > 0) { rust_error_at (expr.get_locus (), @@ -1513,6 +1649,8 @@ CompileExpr::compile_float_literal (const HIR::LiteralExpr &expr, rust_assert (expr.get_lit_type () == HIR::Literal::FLOAT); const auto literal_value = expr.get_literal (); + tree type = TyTyResolveCompile::compile (ctx, tyty); + mpfr_t fval; if (mpfr_init_set_str (fval, literal_value.as_string ().c_str (), 10, MPFR_RNDN) @@ -1522,12 +1660,44 @@ CompileExpr::compile_float_literal (const HIR::LiteralExpr &expr, return error_mark_node; } - tree type = TyTyResolveCompile::compile (ctx, tyty); - // taken from: // see go/gofrontend/expressions.cc:check_float_type - mpfr_exp_t exp = mpfr_get_exp (fval); - bool real_value_overflow = exp > TYPE_PRECISION (type); + bool real_value_overflow; + + if (mpfr_regular_p (fval) != 0) + { + mpfr_exp_t exp = mpfr_get_exp (fval); + mpfr_exp_t min_exp; + mpfr_exp_t max_exp; + + /* + * By convention, the radix point of the significand is just before the + * first digit (which is always 1 due to normalization), like in the C + * language, but unlike in IEEE 754 (thus, for a given number, the + * exponent values in MPFR and in IEEE 754 differ by 1). + */ + switch (TYPE_PRECISION (type)) + { + case 32: + min_exp = -128 + 1; + max_exp = 127 + 1; + break; + case 64: + min_exp = -1024 + 1; + max_exp = 1023 + 1; + break; + default: + rust_error_at (expr.get_locus (), + "precision of type %<%s%> not supported", + tyty->get_name ().c_str ()); + return error_mark_node; + } + real_value_overflow = exp < min_exp || exp > max_exp; + } + else + { + real_value_overflow = false; + } REAL_VALUE_TYPE r1; real_from_mpfr (&r1, fval, type, GMP_RNDN); @@ -1723,7 +1893,7 @@ CompileExpr::visit (HIR::ArrayExpr &expr) const TyTy::ArrayType &array_tyty = static_cast<const TyTy::ArrayType &> (*tyty); - HIR::ArrayElems &elements = *expr.get_internal_elements (); + HIR::ArrayElems &elements = expr.get_internal_elements (); switch (elements.get_array_expr_type ()) { case HIR::ArrayElems::ArrayExprType::VALUES: { @@ -1752,7 +1922,15 @@ CompileExpr::array_value_expr (location_t expr_locus, size_t i = 0; for (auto &elem : elems.get_values ()) { - tree translated_expr = CompileExpr::Compile (elem.get (), ctx); + tree translated_expr = CompileExpr::Compile (*elem, ctx); + if (translated_expr == error_mark_node) + { + rich_location r (line_table, expr_locus); + r.add_fixit_replace (elem->get_locus (), "not a value"); + rust_error_at (r, ErrorCode::E0423, "expected value"); + return error_mark_node; + } + constructor.push_back (translated_expr); indexes.push_back (i++); } @@ -1779,8 +1957,7 @@ CompileExpr::array_copied_expr (location_t expr_locus, } ctx->push_const_context (); - tree capacity_expr - = CompileExpr::Compile (elems.get_num_copies_expr ().get (), ctx); + tree capacity_expr = CompileExpr::Compile (elems.get_num_copies_expr (), ctx); ctx->pop_const_context (); if (!TREE_CONSTANT (capacity_expr)) @@ -1790,8 +1967,7 @@ CompileExpr::array_copied_expr (location_t expr_locus, } // get the compiled value - tree translated_expr - = CompileExpr::Compile (elems.get_elem_to_copy ().get (), ctx); + tree translated_expr = CompileExpr::Compile (elems.get_elem_to_copy (), ctx); tree max_domain = TYPE_MAX_VALUE (domain); tree min_domain = TYPE_MIN_VALUE (domain); @@ -1809,8 +1985,12 @@ CompileExpr::array_copied_expr (location_t expr_locus, if (ctx->const_context_p ()) { size_t idx = 0; + std::vector<unsigned long> indexes; std::vector<tree> constructor; + + indexes.reserve (len); + constructor.reserve (len); for (unsigned HOST_WIDE_INT i = 0; i < len; i++) { constructor.push_back (translated_expr); @@ -1856,6 +2036,9 @@ HIRCompileBase::resolve_adjustements ( tree e = expression; for (auto &adjustment : adjustments) { + if (e == error_mark_node) + return error_mark_node; + switch (adjustment.get_type ()) { case Resolver::Adjustment::AdjustmentType::ERROR: @@ -1996,8 +2179,8 @@ HIRCompileBase::resolve_unsized_dyn_adjustment ( void CompileExpr::visit (HIR::RangeFromToExpr &expr) { - tree from = CompileExpr::Compile (expr.get_from_expr ().get (), ctx); - tree to = CompileExpr::Compile (expr.get_to_expr ().get (), ctx); + tree from = CompileExpr::Compile (expr.get_from_expr (), ctx); + tree to = CompileExpr::Compile (expr.get_to_expr (), ctx); if (from == error_mark_node || to == error_mark_node) { translated = error_mark_node; @@ -2019,7 +2202,7 @@ CompileExpr::visit (HIR::RangeFromToExpr &expr) void CompileExpr::visit (HIR::RangeFromExpr &expr) { - tree from = CompileExpr::Compile (expr.get_from_expr ().get (), ctx); + tree from = CompileExpr::Compile (expr.get_from_expr (), ctx); if (from == error_mark_node) { translated = error_mark_node; @@ -2041,7 +2224,7 @@ CompileExpr::visit (HIR::RangeFromExpr &expr) void CompileExpr::visit (HIR::RangeToExpr &expr) { - tree to = CompileExpr::Compile (expr.get_to_expr ().get (), ctx); + tree to = CompileExpr::Compile (expr.get_to_expr (), ctx); if (to == error_mark_node) { translated = error_mark_node; @@ -2076,8 +2259,8 @@ CompileExpr::visit (HIR::RangeFullExpr &expr) void CompileExpr::visit (HIR::RangeFromToInclExpr &expr) { - tree from = CompileExpr::Compile (expr.get_from_expr ().get (), ctx); - tree to = CompileExpr::Compile (expr.get_to_expr ().get (), ctx); + tree from = CompileExpr::Compile (expr.get_from_expr (), ctx); + tree to = CompileExpr::Compile (expr.get_to_expr (), ctx); if (from == error_mark_node || to == error_mark_node) { translated = error_mark_node; @@ -2099,9 +2282,8 @@ CompileExpr::visit (HIR::RangeFromToInclExpr &expr) void CompileExpr::visit (HIR::ArrayIndexExpr &expr) { - tree array_reference - = CompileExpr::Compile (expr.get_array_expr ().get (), ctx); - tree index = CompileExpr::Compile (expr.get_index_expr ().get (), ctx); + tree array_reference = CompileExpr::Compile (expr.get_array_expr (), ctx); + tree index = CompileExpr::Compile (expr.get_index_expr (), ctx); // this might be an core::ops::index lang item situation TyTy::FnType *fntype; @@ -2112,8 +2294,8 @@ CompileExpr::visit (HIR::ArrayIndexExpr &expr) auto lang_item_type = LangItem::Kind::INDEX; tree operator_overload_call = resolve_operator_overload (lang_item_type, expr, array_reference, - index, expr.get_array_expr ().get (), - expr.get_index_expr ().get ()); + index, expr.get_array_expr (), + expr.get_index_expr ()); tree actual_type = TREE_TYPE (operator_overload_call); bool can_indirect = TYPE_PTR_P (actual_type) || TYPE_REF_P (actual_type); @@ -2135,7 +2317,7 @@ CompileExpr::visit (HIR::ArrayIndexExpr &expr) // indirection if required TyTy::BaseType *array_expr_ty = nullptr; bool ok = ctx->get_tyctx ()->lookup_type ( - expr.get_array_expr ()->get_mappings ().get_hirid (), &array_expr_ty); + expr.get_array_expr ().get_mappings ().get_hirid (), &array_expr_ty); rust_assert (ok); // do we need to add an indirect reference @@ -2174,20 +2356,21 @@ CompileExpr::visit (HIR::ClosureExpr &expr) for (const auto &capture : closure_tyty->get_captures ()) { // lookup the HirId - HirId ref = UNKNOWN_HIRID; - bool ok = ctx->get_mappings ()->lookup_node_to_hir (capture, &ref); - rust_assert (ok); - - // lookup the var decl - Bvariable *var = nullptr; - bool found = ctx->lookup_var_decl (ref, &var); - rust_assert (found); - - // FIXME - // this should bes based on the closure move-ability - tree var_expr = var->get_tree (expr.get_locus ()); - tree val = address_expression (var_expr, expr.get_locus ()); - vals.push_back (val); + if (auto hid = ctx->get_mappings ().lookup_node_to_hir (capture)) + { + // lookup the var decl + Bvariable *var = nullptr; + bool found = ctx->lookup_var_decl (*hid, &var); + rust_assert (found); + + // FIXME + // this should bes based on the closure move-ability + tree var_expr = var->get_tree (expr.get_locus ()); + tree val = address_expression (var_expr, expr.get_locus ()); + vals.push_back (val); + } + else + rust_unreachable (); } translated = Backend::constructor_expression (compiled_closure_tyty, false, @@ -2208,10 +2391,12 @@ CompileExpr::generate_closure_function (HIR::ClosureExpr &expr, const Resolver::CanonicalPath &parent_canonical_path = closure_tyty.get_ident ().path; - NodeId node_id; - bool ok = ctx->get_mappings ()->lookup_hir_to_node ( - expr.get_mappings ().get_hirid (), &node_id); - rust_assert (ok); + + tl::optional<NodeId> nid = ctx->get_mappings ().lookup_hir_to_node ( + expr.get_mappings ().get_hirid ()); + rust_assert (nid.has_value ()); + auto node_id = nid.value (); + Resolver::CanonicalPath path = parent_canonical_path.append ( Resolver::CanonicalPath::new_seg (node_id, "{{closure}}")); @@ -2244,21 +2429,21 @@ CompileExpr::generate_closure_function (HIR::ClosureExpr &expr, for (const auto &capture : closure_tyty.get_captures ()) { // lookup the HirId - HirId ref = UNKNOWN_HIRID; - bool ok = ctx->get_mappings ()->lookup_node_to_hir (capture, &ref); - rust_assert (ok); - - // get the assessor - tree binding = Backend::struct_field_expression (self_param->get_tree ( - expr.get_locus ()), - idx, expr.get_locus ()); - tree indirection = indirect_expression (binding, expr.get_locus ()); + if (auto hid = ctx->get_mappings ().lookup_node_to_hir (capture)) + { + // get the assessor + tree binding = Backend::struct_field_expression ( + self_param->get_tree (expr.get_locus ()), idx, expr.get_locus ()); + tree indirection = indirect_expression (binding, expr.get_locus ()); - // insert bindings - ctx->insert_closure_binding (ref, indirection); + // insert bindings + ctx->insert_closure_binding (*hid, indirection); - // continue - idx++; + // continue + idx++; + } + else + rust_unreachable (); } // args tuple @@ -2283,7 +2468,7 @@ CompileExpr::generate_closure_function (HIR::ClosureExpr &expr, = Backend::struct_field_expression (args_param_expr, i, closure_param.get_locus ()); - CompilePatternBindings::Compile (closure_param.get_pattern ().get (), + CompilePatternBindings::Compile (closure_param.get_pattern (), compiled_param_var, ctx); i++; } @@ -2295,16 +2480,16 @@ CompileExpr::generate_closure_function (HIR::ClosureExpr &expr, } // lookup locals - HIR::Expr *function_body = expr.get_expr ().get (); + HIR::Expr &function_body = expr.get_expr (); bool is_block_expr - = function_body->get_expression_type () == HIR::Expr::ExprType::Block; + = function_body.get_expression_type () == HIR::Expr::ExprType::Block; if (is_block_expr) { - auto body_mappings = function_body->get_mappings (); + auto body_mappings = function_body.get_mappings (); if (flag_name_resolution_2_0) { - auto nr_ctx + auto &nr_ctx = Resolver2_0::ImmutableNameResolutionContext::get ().resolver (); auto candidate = nr_ctx.values.to_rib (body_mappings.get_nodeid ()); @@ -2322,13 +2507,13 @@ CompileExpr::generate_closure_function (HIR::ClosureExpr &expr, } tree enclosing_scope = NULL_TREE; - location_t start_location = function_body->get_locus (); - location_t end_location = function_body->get_locus (); + location_t start_location = function_body.get_locus (); + location_t end_location = function_body.get_locus (); if (is_block_expr) { - HIR::BlockExpr *body = static_cast<HIR::BlockExpr *> (function_body); - start_location = body->get_locus (); - end_location = body->get_end_locus (); + auto &body = static_cast<HIR::BlockExpr &> (function_body); + start_location = body.get_locus (); + end_location = body.get_end_locus (); } tree code_block = Backend::block (fndecl, enclosing_scope, {} /*locals*/, @@ -2353,15 +2538,14 @@ CompileExpr::generate_closure_function (HIR::ClosureExpr &expr, if (is_block_expr) { - HIR::BlockExpr *body = static_cast<HIR::BlockExpr *> (function_body); - compile_function_body (fndecl, *body, tyret); + auto &body = static_cast<HIR::BlockExpr &> (function_body); + compile_function_body (fndecl, body, tyret); } else { tree value = CompileExpr::Compile (function_body, ctx); tree return_expr - = Backend::return_statement (fndecl, value, - function_body->get_locus ()); + = Backend::return_statement (fndecl, value, function_body.get_locus ()); ctx->add_statement (return_expr); } @@ -2448,8 +2632,8 @@ CompileExpr::generate_possible_fn_trait_call (HIR::CallExpr &expr, } // need to apply any autoderef's to the self argument - HIR::Expr *fnexpr = expr.get_fnexpr ().get (); - HirId autoderef_mappings_id = fnexpr->get_mappings ().get_hirid (); + HIR::Expr &fnexpr = expr.get_fnexpr (); + HirId autoderef_mappings_id = fnexpr.get_mappings ().get_hirid (); std::vector<Resolver::Adjustment> *adjustments = nullptr; bool ok = ctx->get_tyctx ()->lookup_autoderef_mappings (autoderef_mappings_id, &adjustments); @@ -2462,7 +2646,7 @@ CompileExpr::generate_possible_fn_trait_call (HIR::CallExpr &expr, std::vector<tree> tuple_arg_vals; for (auto &argument : expr.get_arguments ()) { - auto rvalue = CompileExpr::Compile (argument.get (), ctx); + auto rvalue = CompileExpr::Compile (*argument, ctx); tuple_arg_vals.push_back (rvalue); } diff --git a/gcc/rust/backend/rust-compile-expr.h b/gcc/rust/backend/rust-compile-expr.h index af2e1bc..fda508d 100644 --- a/gcc/rust/backend/rust-compile-expr.h +++ b/gcc/rust/backend/rust-compile-expr.h @@ -28,7 +28,7 @@ namespace Compile { class CompileExpr : private HIRCompileBase, protected HIR::HIRExpressionVisitor { public: - static tree Compile (HIR::Expr *expr, Context *ctx); + static tree Compile (HIR::Expr &expr, Context *ctx); void visit (HIR::TupleIndexExpr &expr) override; void visit (HIR::TupleExpr &expr) override; @@ -48,6 +48,8 @@ public: void visit (HIR::IfExpr &expr) override; void visit (HIR::IfExprConseqElse &expr) override; void visit (HIR::BlockExpr &expr) override; + void visit (HIR::AnonConst &expr) override; + void visit (HIR::ConstBlock &expr) override; void visit (HIR::UnsafeBlockExpr &expr) override; void visit (HIR::StructExprStruct &struct_expr) override; void visit (HIR::StructExprStructFields &struct_expr) override; @@ -68,6 +70,8 @@ public: void visit (HIR::RangeFullExpr &expr) override; void visit (HIR::RangeFromToInclExpr &expr) override; void visit (HIR::ClosureExpr &expr) override; + void visit (HIR::InlineAsm &expr) override; + void visit (HIR::LlvmInlineAsm &expr) override; // TODO void visit (HIR::ErrorPropagationExpr &) override {} @@ -76,8 +80,6 @@ public: // TODO // these need to be sugared in the HIR to if statements and a match void visit (HIR::WhileLetLoopExpr &) override {} - void visit (HIR::IfLetExpr &) override {} - void visit (HIR::IfLetExprConseqElse &) override {} // lets not worry about async yet.... void visit (HIR::AwaitExpr &) override {} @@ -97,10 +99,12 @@ protected: TyTy::BaseType *receiver, TyTy::FnType *fntype, tree receiver_ref, location_t expr_locus); - tree resolve_operator_overload (LangItem::Kind lang_item_type, - HIR::OperatorExprMeta expr, tree lhs, - tree rhs, HIR::Expr *lhs_expr, - HIR::Expr *rhs_expr); + tree resolve_operator_overload ( + LangItem::Kind lang_item_type, HIR::OperatorExprMeta expr, tree lhs, + tree rhs, HIR::Expr &lhs_expr, + tl::optional<std::reference_wrapper<HIR::Expr>> rhs_expr, + HIR::PathIdentSegment specified_segment + = HIR::PathIdentSegment::create_error ()); tree compile_bool_literal (const HIR::LiteralExpr &expr, const TyTy::BaseType *tyty); diff --git a/gcc/rust/backend/rust-compile-extern.h b/gcc/rust/backend/rust-compile-extern.h index b17ac95..aa4a0c3 100644 --- a/gcc/rust/backend/rust-compile-extern.h +++ b/gcc/rust/backend/rust-compile-extern.h @@ -34,16 +34,10 @@ class CompileExternItem : public HIRCompileBase, public: static tree compile (HIR::ExternalItem *item, Context *ctx, TyTy::BaseType *concrete = nullptr, - bool is_query_mode = false, location_t ref_locus = UNDEF_LOCATION) { CompileExternItem compiler (ctx, concrete, ref_locus); item->accept_vis (compiler); - - if (is_query_mode && compiler.reference == error_mark_node) - rust_internal_error_at (ref_locus, "failed to compile extern item: %s", - item->as_string ().c_str ()); - return compiler.reference; } @@ -134,10 +128,8 @@ public: if (fntype->get_abi () == ABI::RUST) { // then we need to get the canonical path of it and mangle it - const Resolver::CanonicalPath *canonical_path = nullptr; - bool ok = ctx->get_mappings ()->lookup_canonical_path ( - function.get_mappings ().get_nodeid (), &canonical_path); - rust_assert (ok); + auto canonical_path = ctx->get_mappings ().lookup_canonical_path ( + function.get_mappings ().get_nodeid ()); ir_symbol_name = canonical_path->get () + fntype->subst_as_string (); asm_name = ctx->mangle_item (fntype, *canonical_path); diff --git a/gcc/rust/backend/rust-compile-fnparam.cc b/gcc/rust/backend/rust-compile-fnparam.cc index 68066b8..bb3e06c 100644 --- a/gcc/rust/backend/rust-compile-fnparam.cc +++ b/gcc/rust/backend/rust-compile-fnparam.cc @@ -31,20 +31,20 @@ CompileFnParam::CompileFnParam (Context *ctx, tree fndecl, tree decl_type, {} Bvariable * -CompileFnParam::compile (Context *ctx, tree fndecl, HIR::FunctionParam *param, +CompileFnParam::compile (Context *ctx, tree fndecl, HIR::FunctionParam ¶m, tree decl_type, location_t locus) { CompileFnParam compiler (ctx, fndecl, decl_type, locus); - param->get_param_name ()->accept_vis (compiler); + param.get_param_name ().accept_vis (compiler); return compiler.compiled_param; } Bvariable * -CompileFnParam::compile (Context *ctx, tree fndecl, HIR::Pattern *param, +CompileFnParam::compile (Context *ctx, tree fndecl, HIR::Pattern ¶m, tree decl_type, location_t locus) { CompileFnParam compiler (ctx, fndecl, decl_type, locus); - param->accept_vis (compiler); + param.accept_vis (compiler); return compiler.compiled_param; } @@ -69,24 +69,35 @@ CompileFnParam::visit (HIR::WildcardPattern &pattern) } void +CompileFnParam::visit (HIR::TuplePattern &pattern) +{ + compiled_param = create_tmp_param_var (decl_type); + CompilePatternBindings::Compile ( + pattern, Backend::var_expression (compiled_param, locus), ctx); +} + +void CompileFnParam::visit (HIR::StructPattern &pattern) { - tree tmp_param_var = create_tmp_param_var (decl_type); - CompilePatternBindings::Compile (&pattern, tmp_param_var, ctx); + compiled_param = create_tmp_param_var (decl_type); + CompilePatternBindings::Compile ( + pattern, Backend::var_expression (compiled_param, locus), ctx); } void CompileFnParam::visit (HIR::TupleStructPattern &pattern) { - tree tmp_param_var = create_tmp_param_var (decl_type); - CompilePatternBindings::Compile (&pattern, tmp_param_var, ctx); + compiled_param = create_tmp_param_var (decl_type); + CompilePatternBindings::Compile ( + pattern, Backend::var_expression (compiled_param, locus), ctx); } void CompileFnParam::visit (HIR::ReferencePattern &pattern) { - tree tmp_param_var = create_tmp_param_var (decl_type); - CompilePatternBindings::Compile (&pattern, tmp_param_var, ctx); + compiled_param = create_tmp_param_var (decl_type); + CompilePatternBindings::Compile ( + pattern, Backend::var_expression (compiled_param, locus), ctx); } Bvariable * @@ -102,7 +113,7 @@ CompileSelfParam::compile (Context *ctx, tree fndecl, HIR::SelfParam &self, return Backend::parameter_variable (fndecl, "self", decl_type, locus); } -tree +Bvariable * CompileFnParam::create_tmp_param_var (tree decl_type) { // generate the anon param @@ -110,10 +121,8 @@ CompileFnParam::create_tmp_param_var (tree decl_type) std::string cpp_str_identifier = std::string (IDENTIFIER_POINTER (tmp_ident)); decl_type = Backend::immutable_type (decl_type); - compiled_param = Backend::parameter_variable (fndecl, cpp_str_identifier, - decl_type, locus); - - return Backend::var_expression (compiled_param, locus); + return Backend::parameter_variable (fndecl, cpp_str_identifier, decl_type, + locus); } } // namespace Compile diff --git a/gcc/rust/backend/rust-compile-fnparam.h b/gcc/rust/backend/rust-compile-fnparam.h index 9b50b19..fed0168 100644 --- a/gcc/rust/backend/rust-compile-fnparam.h +++ b/gcc/rust/backend/rust-compile-fnparam.h @@ -29,9 +29,9 @@ class CompileFnParam : private HIRCompileBase, protected HIR::HIRPatternVisitor { public: static Bvariable *compile (Context *ctx, tree fndecl, - HIR::FunctionParam *param, tree decl_type, + HIR::FunctionParam ¶m, tree decl_type, location_t locus); - static Bvariable *compile (Context *ctx, tree fndecl, HIR::Pattern *param, + static Bvariable *compile (Context *ctx, tree fndecl, HIR::Pattern ¶m, tree decl_type, location_t locus); void visit (HIR::IdentifierPattern &pattern) override; @@ -47,12 +47,12 @@ public: void visit (HIR::QualifiedPathInExpression &) override {} void visit (HIR::RangePattern &) override {} void visit (HIR::SlicePattern &) override {} - void visit (HIR::TuplePattern &) override {} + void visit (HIR::TuplePattern &) override; private: CompileFnParam (Context *ctx, tree fndecl, tree decl_type, location_t locus); - tree create_tmp_param_var (tree decl_type); + Bvariable *create_tmp_param_var (tree decl_type); tree fndecl; tree decl_type; diff --git a/gcc/rust/backend/rust-compile-implitem.cc b/gcc/rust/backend/rust-compile-implitem.cc index 824af3f..a30e11f 100644 --- a/gcc/rust/backend/rust-compile-implitem.cc +++ b/gcc/rust/backend/rust-compile-implitem.cc @@ -27,15 +27,34 @@ CompileTraitItem::visit (HIR::TraitItemConst &constant) rust_assert (concrete != nullptr); TyTy::BaseType *resolved_type = concrete; - const Resolver::CanonicalPath *canonical_path = nullptr; - bool ok = ctx->get_mappings ()->lookup_canonical_path ( - constant.get_mappings ().get_nodeid (), &canonical_path); + tl::optional<Resolver::CanonicalPath> canonical_path; + if (flag_name_resolution_2_0) + { + auto &nr_ctx + = Resolver2_0::ImmutableNameResolutionContext::get ().resolver (); + + canonical_path = nr_ctx.values.to_canonical_path ( + constant.get_mappings ().get_nodeid ()); + } + else + { + canonical_path = ctx->get_mappings ().lookup_canonical_path ( + constant.get_mappings ().get_nodeid ()); + } + + rust_assert (canonical_path); + + HIR::Expr &const_value_expr = constant.get_expr (); + TyTy::BaseType *expr_type = nullptr; + bool ok = ctx->get_tyctx ()->lookup_type ( + const_value_expr.get_mappings ().get_hirid (), &expr_type); rust_assert (ok); - HIR::Expr *const_value_expr = constant.get_expr ().get (); tree const_expr - = compile_constant_item (resolved_type, canonical_path, const_value_expr, - constant.get_locus ()); + = compile_constant_item (constant.get_mappings ().get_hirid (), expr_type, + resolved_type, *canonical_path, const_value_expr, + constant.get_locus (), + const_value_expr.get_locus ()); ctx->push_const (const_expr); ctx->insert_const_decl (constant.get_mappings ().get_hirid (), const_expr); @@ -45,7 +64,7 @@ CompileTraitItem::visit (HIR::TraitItemConst &constant) void CompileTraitItem::visit (HIR::TraitItemFunc &func) { - rust_assert (func.has_block_defined ()); + rust_assert (func.has_definition ()); rust_assert (concrete->get_kind () == TyTy::TypeKind::FNDEF); TyTy::FnType *fntype = static_cast<TyTy::FnType *> (concrete); @@ -77,20 +96,32 @@ CompileTraitItem::visit (HIR::TraitItemFunc &func) fntype->override_context (); } - const Resolver::CanonicalPath *canonical_path = nullptr; - bool ok = ctx->get_mappings ()->lookup_canonical_path ( - func.get_mappings ().get_nodeid (), &canonical_path); - rust_assert (ok); + tl::optional<Resolver::CanonicalPath> canonical_path; + if (flag_name_resolution_2_0) + { + auto &nr_ctx + = Resolver2_0::ImmutableNameResolutionContext::get ().resolver (); + + canonical_path + = nr_ctx.values.to_canonical_path (func.get_mappings ().get_nodeid ()); + } + else + { + canonical_path = ctx->get_mappings ().lookup_canonical_path ( + func.get_mappings ().get_nodeid ()); + } + + rust_assert (canonical_path); // FIXME: How do we get the proper visibility here? auto vis = HIR::Visibility (HIR::Visibility::VisType::PUBLIC); HIR::TraitFunctionDecl &function = func.get_decl (); tree fndecl - = compile_function (function.get_function_name ().as_string (), + = compile_function (false, function.get_function_name ().as_string (), function.get_self (), function.get_function_params (), function.get_qualifiers (), vis, func.get_outer_attrs (), func.get_locus (), - func.get_block_expr ().get (), canonical_path, fntype); + &func.get_block_expr (), *canonical_path, fntype); reference = address_expression (fndecl, ref_locus); } diff --git a/gcc/rust/backend/rust-compile-implitem.h b/gcc/rust/backend/rust-compile-implitem.h index 69933bf..22189d4 100644 --- a/gcc/rust/backend/rust-compile-implitem.h +++ b/gcc/rust/backend/rust-compile-implitem.h @@ -30,16 +30,10 @@ class CompileInherentImplItem : public CompileItem public: static tree Compile (HIR::ImplItem *item, Context *ctx, TyTy::BaseType *concrete = nullptr, - bool is_query_mode = false, location_t ref_locus = UNDEF_LOCATION) { CompileInherentImplItem compiler (ctx, concrete, ref_locus); item->accept_vis (compiler); - - if (is_query_mode && compiler.reference == error_mark_node) - rust_internal_error_at (ref_locus, "failed to compile impl item: %s", - item->as_string ().c_str ()); - return compiler.reference; } diff --git a/gcc/rust/backend/rust-compile-intrinsic.cc b/gcc/rust/backend/rust-compile-intrinsic.cc index 49ee4c0..cd79a7b 100644 --- a/gcc/rust/backend/rust-compile-intrinsic.cc +++ b/gcc/rust/backend/rust-compile-intrinsic.cc @@ -17,23 +17,19 @@ #include "rust-compile-intrinsic.h" #include "rust-compile-context.h" #include "rust-compile-type.h" -#include "rust-compile-expr.h" #include "rust-compile-fnparam.h" #include "rust-builtins.h" #include "rust-diagnostics.h" #include "rust-location.h" #include "rust-constexpr.h" +#include "rust-session-manager.h" #include "rust-tree.h" #include "tree-core.h" #include "rust-gcc.h" -#include "print-tree.h" #include "fold-const.h" #include "langhooks.h" -#include "rust-gcc.h" #include "rust-constexpr.h" -#include "print-tree.h" - // declaration taken from "stringpool.h" // the get_identifier macro causes compilation issues extern tree @@ -92,6 +88,10 @@ static tree move_val_init_handler (Context *ctx, TyTy::FnType *fntype); static tree assume_handler (Context *ctx, TyTy::FnType *fntype); +static tree +discriminant_value_handler (Context *ctx, TyTy::FnType *fntype); +static tree +variant_count_handler (Context *ctx, TyTy::FnType *fntype); enum class Prefetch { @@ -194,6 +194,17 @@ expect_handler (bool likely) }; } +static tree +try_handler_inner (Context *ctx, TyTy::FnType *fntype, bool is_new_api); + +const static std::function<tree (Context *, TyTy::FnType *)> +try_handler (bool is_new_api) +{ + return [is_new_api] (Context *ctx, TyTy::FnType *fntype) { + return try_handler_inner (ctx, fntype, is_new_api); + }; +} + inline tree sorry_handler (Context *ctx, TyTy::FnType *fntype) { @@ -205,43 +216,46 @@ sorry_handler (Context *ctx, TyTy::FnType *fntype) static const std::map<std::string, std::function<tree (Context *, TyTy::FnType *)>> - generic_intrinsics = { - {"offset", offset_handler}, - {"size_of", sizeof_handler}, - {"transmute", transmute_handler}, - {"rotate_left", rotate_left_handler}, - {"rotate_right", rotate_right_handler}, - {"wrapping_add", wrapping_op_handler (PLUS_EXPR)}, - {"wrapping_sub", wrapping_op_handler (MINUS_EXPR)}, - {"wrapping_mul", wrapping_op_handler (MULT_EXPR)}, - {"add_with_overflow", op_with_overflow (PLUS_EXPR)}, - {"sub_with_overflow", op_with_overflow (MINUS_EXPR)}, - {"mul_with_overflow", op_with_overflow (MULT_EXPR)}, - {"copy", copy_handler (true)}, - {"copy_nonoverlapping", copy_handler (false)}, - {"prefetch_read_data", prefetch_read_data}, - {"prefetch_write_data", prefetch_write_data}, - {"atomic_store_seqcst", atomic_store_handler (__ATOMIC_SEQ_CST)}, - {"atomic_store_release", atomic_store_handler (__ATOMIC_RELEASE)}, - {"atomic_store_relaxed", atomic_store_handler (__ATOMIC_RELAXED)}, - {"atomic_store_unordered", atomic_store_handler (__ATOMIC_RELAXED)}, - {"atomic_load_seqcst", atomic_load_handler (__ATOMIC_SEQ_CST)}, - {"atomic_load_acquire", atomic_load_handler (__ATOMIC_ACQUIRE)}, - {"atomic_load_relaxed", atomic_load_handler (__ATOMIC_RELAXED)}, - {"atomic_load_unordered", atomic_load_handler (__ATOMIC_RELAXED)}, - {"unchecked_add", unchecked_op_handler (PLUS_EXPR)}, - {"unchecked_sub", unchecked_op_handler (MINUS_EXPR)}, - {"unchecked_mul", unchecked_op_handler (MULT_EXPR)}, - {"unchecked_div", unchecked_op_handler (TRUNC_DIV_EXPR)}, - {"unchecked_rem", unchecked_op_handler (TRUNC_MOD_EXPR)}, - {"unchecked_shl", unchecked_op_handler (LSHIFT_EXPR)}, - {"unchecked_shr", unchecked_op_handler (RSHIFT_EXPR)}, - {"uninit", uninit_handler}, - {"move_val_init", move_val_init_handler}, - {"likely", expect_handler (true)}, - {"unlikely", expect_handler (false)}, - {"assume", assume_handler}, -}; + generic_intrinsics + = {{"offset", offset_handler}, + {"size_of", sizeof_handler}, + {"transmute", transmute_handler}, + {"rotate_left", rotate_left_handler}, + {"rotate_right", rotate_right_handler}, + {"wrapping_add", wrapping_op_handler (PLUS_EXPR)}, + {"wrapping_sub", wrapping_op_handler (MINUS_EXPR)}, + {"wrapping_mul", wrapping_op_handler (MULT_EXPR)}, + {"add_with_overflow", op_with_overflow (PLUS_EXPR)}, + {"sub_with_overflow", op_with_overflow (MINUS_EXPR)}, + {"mul_with_overflow", op_with_overflow (MULT_EXPR)}, + {"copy", copy_handler (true)}, + {"copy_nonoverlapping", copy_handler (false)}, + {"prefetch_read_data", prefetch_read_data}, + {"prefetch_write_data", prefetch_write_data}, + {"atomic_store_seqcst", atomic_store_handler (__ATOMIC_SEQ_CST)}, + {"atomic_store_release", atomic_store_handler (__ATOMIC_RELEASE)}, + {"atomic_store_relaxed", atomic_store_handler (__ATOMIC_RELAXED)}, + {"atomic_store_unordered", atomic_store_handler (__ATOMIC_RELAXED)}, + {"atomic_load_seqcst", atomic_load_handler (__ATOMIC_SEQ_CST)}, + {"atomic_load_acquire", atomic_load_handler (__ATOMIC_ACQUIRE)}, + {"atomic_load_relaxed", atomic_load_handler (__ATOMIC_RELAXED)}, + {"atomic_load_unordered", atomic_load_handler (__ATOMIC_RELAXED)}, + {"unchecked_add", unchecked_op_handler (PLUS_EXPR)}, + {"unchecked_sub", unchecked_op_handler (MINUS_EXPR)}, + {"unchecked_mul", unchecked_op_handler (MULT_EXPR)}, + {"unchecked_div", unchecked_op_handler (TRUNC_DIV_EXPR)}, + {"unchecked_rem", unchecked_op_handler (TRUNC_MOD_EXPR)}, + {"unchecked_shl", unchecked_op_handler (LSHIFT_EXPR)}, + {"unchecked_shr", unchecked_op_handler (RSHIFT_EXPR)}, + {"uninit", uninit_handler}, + {"move_val_init", move_val_init_handler}, + {"likely", expect_handler (true)}, + {"unlikely", expect_handler (false)}, + {"assume", assume_handler}, + {"try", try_handler (false)}, + {"catch_unwind", try_handler (true)}, + {"discriminant_value", discriminant_value_handler}, + {"variant_count", variant_count_handler}}; Intrinsics::Intrinsics (Context *ctx) : ctx (ctx) {} @@ -269,7 +283,7 @@ Intrinsics::compile (TyTy::FnType *fntype) if (it != generic_intrinsics.end ()) return it->second (ctx, fntype); - location_t locus = ctx->get_mappings ()->lookup_location (fntype->get_ref ()); + location_t locus = ctx->get_mappings ().lookup_location (fntype->get_ref ()); rust_error_at (locus, ErrorCode::E0093, "unrecognized intrinsic function: %<%s%>", fntype->get_identifier ().c_str ()); @@ -315,11 +329,11 @@ compile_fn_params (Context *ctx, TyTy::FnType *fntype, tree fndecl, { for (auto &parm : fntype->get_params ()) { - auto &referenced_param = parm.first; - auto ¶m_tyty = parm.second; + auto &referenced_param = parm.get_pattern (); + auto param_tyty = parm.get_type (); auto compiled_param_type = TyTyResolveCompile::compile (ctx, param_tyty); - location_t param_locus = referenced_param->get_locus (); + location_t param_locus = referenced_param.get_locus (); Bvariable *compiled_param_var = CompileFnParam::compile (ctx, fndecl, referenced_param, compiled_param_type, param_locus); @@ -496,9 +510,10 @@ transmute_handler (Context *ctx, TyTy::FnType *fntype) rust_error_at (fntype->get_locus (), "cannot transmute between types of different sizes, or " "dependently-sized types"); - rust_inform (fntype->get_ident ().locus, "source type: %qs (%lu bits)", - fntype->get_params ().at (0).second->as_string ().c_str (), - (unsigned long) source_size); + rust_inform ( + fntype->get_ident ().locus, "source type: %qs (%lu bits)", + fntype->get_params ().at (0).get_type ()->as_string ().c_str (), + (unsigned long) source_size); rust_inform (fntype->get_ident ().locus, "target type: %qs (%lu bits)", fntype->get_return_type ()->as_string ().c_str (), (unsigned long) target_size); @@ -1226,7 +1241,7 @@ assume_handler (Context *ctx, TyTy::FnType *fntype) // TODO: make sure this is actually helping the compiler optimize rust_assert (fntype->get_params ().size () == 1); - rust_assert (fntype->param_at (0).second->get_kind () + rust_assert (fntype->param_at (0).get_type ()->get_kind () == TyTy::TypeKind::BOOL); tree lookup = NULL_TREE; @@ -1258,7 +1273,217 @@ assume_handler (Context *ctx, TyTy::FnType *fntype) TREE_SIDE_EFFECTS (assume_expr) = 1; ctx->add_statement (assume_expr); - // BUILTIN size_of FN BODY END + // BUILTIN assume FN BODY END + + finalize_intrinsic_block (ctx, fndecl); + + return fndecl; +} + +static tree +try_handler_inner (Context *ctx, TyTy::FnType *fntype, bool is_new_api) +{ + rust_assert (fntype->get_params ().size () == 3); + + tree lookup = NULL_TREE; + if (check_for_cached_intrinsic (ctx, fntype, &lookup)) + return lookup; + auto fndecl = compile_intrinsic_function (ctx, fntype); + + enter_intrinsic_block (ctx, fndecl); + + // The following tricks are needed to make sure the try-catch blocks are not + // optimized away + TREE_READONLY (fndecl) = 0; + DECL_DISREGARD_INLINE_LIMITS (fndecl) = 1; + DECL_ATTRIBUTES (fndecl) = tree_cons (get_identifier ("always_inline"), + NULL_TREE, DECL_ATTRIBUTES (fndecl)); + + // BUILTIN try_handler FN BODY BEGIN + // setup the params + std::vector<Bvariable *> param_vars; + compile_fn_params (ctx, fntype, fndecl, ¶m_vars); + if (!Backend::function_set_parameters (fndecl, param_vars)) + return error_mark_node; + tree enclosing_scope = NULL_TREE; + + bool panic_is_abort = Session::get_instance ().options.get_panic_strategy () + == CompileOptions::PanicStrategy::Abort; + tree try_fn = Backend::var_expression (param_vars[0], UNDEF_LOCATION); + tree user_data = Backend::var_expression (param_vars[1], UNDEF_LOCATION); + tree catch_fn = Backend::var_expression (param_vars[2], UNDEF_LOCATION); + tree normal_return_stmt = NULL_TREE; + tree error_return_stmt = NULL_TREE; + tree try_call = Backend::call_expression (try_fn, {user_data}, nullptr, + BUILTINS_LOCATION); + tree catch_call = NULL_TREE; + tree try_block = Backend::block (fndecl, enclosing_scope, {}, UNDEF_LOCATION, + UNDEF_LOCATION); + + if (is_new_api) + { + auto ret_type = TyTyResolveCompile::get_unit_type (ctx); + auto ret_expr = Backend::constructor_expression (ret_type, false, {}, -1, + UNDEF_LOCATION); + normal_return_stmt + = Backend::return_statement (fndecl, ret_expr, BUILTINS_LOCATION); + error_return_stmt + = Backend::return_statement (fndecl, ret_expr, BUILTINS_LOCATION); + } + else + { + normal_return_stmt = Backend::return_statement (fndecl, integer_zero_node, + BUILTINS_LOCATION); + error_return_stmt = Backend::return_statement (fndecl, integer_one_node, + BUILTINS_LOCATION); + } + Backend::block_add_statements (try_block, + std::vector<tree>{try_call, + normal_return_stmt}); + if (panic_is_abort) + { + // skip building the try-catch construct + ctx->add_statement (try_block); + finalize_intrinsic_block (ctx, fndecl); + return fndecl; + } + + tree eh_pointer + = build_call_expr (builtin_decl_explicit (BUILT_IN_EH_POINTER), 1, + integer_zero_node); + catch_call = Backend::call_expression (catch_fn, {user_data, eh_pointer}, + NULL_TREE, BUILTINS_LOCATION); + + tree catch_block = Backend::block (fndecl, enclosing_scope, {}, + UNDEF_LOCATION, UNDEF_LOCATION); + Backend::block_add_statements (catch_block, + std::vector<tree>{catch_call, + error_return_stmt}); + // emulate what cc1plus is doing for C++ try-catch + tree inner_eh_construct + = Backend::exception_handler_statement (catch_call, NULL_TREE, + error_return_stmt, + BUILTINS_LOCATION); + // TODO(liushuyu): eh_personality needs to be implemented as a runtime thing + auto eh_construct + = Backend::exception_handler_statement (try_block, inner_eh_construct, + NULL_TREE, BUILTINS_LOCATION); + ctx->add_statement (eh_construct); + // BUILTIN try_handler FN BODY END + finalize_intrinsic_block (ctx, fndecl); + + return fndecl; +} + +static tree +discriminant_value_handler (Context *ctx, TyTy::FnType *fntype) +{ + rust_assert (fntype->get_params ().size () == 1); + rust_assert (fntype->get_return_type ()->is<TyTy::PlaceholderType> ()); + rust_assert (fntype->has_substitutions ()); + rust_assert (fntype->get_num_type_params () == 1); + auto &mapping = fntype->get_substs ().at (0); + auto param_ty = mapping.get_param_ty (); + rust_assert (param_ty->can_resolve ()); + auto resolved = param_ty->resolve (); + auto p = static_cast<TyTy::PlaceholderType *> (fntype->get_return_type ()); + + TyTy::BaseType *return_type = nullptr; + bool ok = ctx->get_tyctx ()->lookup_builtin ("isize", &return_type); + rust_assert (ok); + + bool is_adt = resolved->is<TyTy::ADTType> (); + bool is_enum = false; + if (is_adt) + { + const auto &adt = *static_cast<TyTy::ADTType *> (resolved); + return_type = adt.get_repr_options ().repr; + rust_assert (return_type != nullptr); + is_enum = adt.is_enum (); + } + + p->set_associated_type (return_type->get_ref ()); + + tree lookup = NULL_TREE; + if (check_for_cached_intrinsic (ctx, fntype, &lookup)) + return lookup; + + auto fndecl = compile_intrinsic_function (ctx, fntype); + + std::vector<Bvariable *> param_vars; + compile_fn_params (ctx, fntype, fndecl, ¶m_vars); + + if (!Backend::function_set_parameters (fndecl, param_vars)) + return error_mark_node; + + enter_intrinsic_block (ctx, fndecl); + + // BUILTIN disriminant_value FN BODY BEGIN + + tree result = integer_zero_node; + if (is_enum) + { + tree val = Backend::var_expression (param_vars[0], UNDEF_LOCATION); + tree deref = build_fold_indirect_ref_loc (UNKNOWN_LOCATION, val); + result = Backend::struct_field_expression (deref, 0, UNKNOWN_LOCATION); + } + + auto return_statement + = Backend::return_statement (fndecl, result, BUILTINS_LOCATION); + ctx->add_statement (return_statement); + + // BUILTIN disriminant_value FN BODY END + + finalize_intrinsic_block (ctx, fndecl); + + return fndecl; +} + +static tree +variant_count_handler (Context *ctx, TyTy::FnType *fntype) +{ + rust_assert (fntype->get_num_type_params () == 1); + auto &mapping = fntype->get_substs ().at (0); + auto param_ty = mapping.get_param_ty (); + rust_assert (param_ty->can_resolve ()); + auto resolved = param_ty->resolve (); + + size_t variant_count = 0; + bool is_adt = resolved->is<TyTy::ADTType> (); + if (is_adt) + { + const auto &adt = *static_cast<TyTy::ADTType *> (resolved); + variant_count = adt.number_of_variants (); + } + + tree lookup = NULL_TREE; + if (check_for_cached_intrinsic (ctx, fntype, &lookup)) + return lookup; + + auto fndecl = compile_intrinsic_function (ctx, fntype); + + std::vector<Bvariable *> param_vars; + compile_fn_params (ctx, fntype, fndecl, ¶m_vars); + + if (!Backend::function_set_parameters (fndecl, param_vars)) + return error_mark_node; + + enter_intrinsic_block (ctx, fndecl); + + // BUILTIN disriminant_value FN BODY BEGIN + tree result_decl = DECL_RESULT (fndecl); + tree type = TREE_TYPE (result_decl); + + mpz_t ival; + mpz_init_set_ui (ival, variant_count); + tree result = wide_int_to_tree (type, wi::from_mpz (type, ival, true)); + mpz_clear (ival); + + auto return_statement + = Backend::return_statement (fndecl, result, BUILTINS_LOCATION); + ctx->add_statement (return_statement); + + // BUILTIN disriminant_value FN BODY END finalize_intrinsic_block (ctx, fndecl); diff --git a/gcc/rust/backend/rust-compile-item.cc b/gcc/rust/backend/rust-compile-item.cc index 609528d..6ed5b39 100644 --- a/gcc/rust/backend/rust-compile-item.cc +++ b/gcc/rust/backend/rust-compile-item.cc @@ -19,6 +19,8 @@ #include "rust-compile-item.h" #include "rust-compile-implitem.h" #include "rust-compile-extern.h" +#include "rust-substitution-mapper.h" +#include "rust-type-util.h" #include "rust-immutable-name-resolution-context.h" namespace Rust { @@ -35,22 +37,42 @@ CompileItem::visit (HIR::StaticItem &var) return; } + HIR::Expr &const_value_expr = var.get_expr (); + TyTy::BaseType *resolved_type = nullptr; + TyTy::BaseType *expr_type = nullptr; bool ok = ctx->get_tyctx ()->lookup_type (var.get_mappings ().get_hirid (), &resolved_type); rust_assert (ok); + ok = ctx->get_tyctx ()->lookup_type ( + const_value_expr.get_mappings ().get_hirid (), &expr_type); + rust_assert (ok); tree type = TyTyResolveCompile::compile (ctx, resolved_type); - const Resolver::CanonicalPath *canonical_path = nullptr; - ok = ctx->get_mappings ()->lookup_canonical_path ( - var.get_mappings ().get_nodeid (), &canonical_path); - rust_assert (ok); + tl::optional<Resolver::CanonicalPath> canonical_path; + + if (flag_name_resolution_2_0) + { + auto &nr_ctx + = Resolver2_0::ImmutableNameResolutionContext::get ().resolver (); + + canonical_path + = nr_ctx.values.to_canonical_path (var.get_mappings ().get_nodeid ()); + } + else + { + canonical_path = ctx->get_mappings ().lookup_canonical_path ( + var.get_mappings ().get_nodeid ()); + } + + rust_assert (canonical_path.has_value ()); - HIR::Expr *const_value_expr = var.get_expr ().get (); ctx->push_const_context (); - tree value = compile_constant_item (resolved_type, canonical_path, - const_value_expr, var.get_locus ()); + tree value + = compile_constant_item (var.get_mappings ().get_hirid (), expr_type, + resolved_type, *canonical_path, const_value_expr, + var.get_locus (), const_value_expr.get_locus ()); ctx->pop_const_context (); std::string name = canonical_path->get (); @@ -76,16 +98,21 @@ CompileItem::visit (HIR::StaticItem &var) void CompileItem::visit (HIR::ConstantItem &constant) { + HIR::Expr &const_value_expr = constant.get_expr (); auto &mappings = constant.get_mappings (); if (ctx->lookup_const_decl (mappings.get_hirid (), &reference)) return; // resolve the type - TyTy::BaseType *resolved_type = nullptr; + TyTy::BaseType *constant_type = nullptr; + TyTy::BaseType *expr_type = nullptr; bool ok - = ctx->get_tyctx ()->lookup_type (mappings.get_hirid (), &resolved_type); + = ctx->get_tyctx ()->lookup_type (mappings.get_hirid (), &constant_type); + rust_assert (ok); + ok = ctx->get_tyctx ()->lookup_type ( + const_value_expr.get_mappings ().get_hirid (), &expr_type); rust_assert (ok); // canonical path @@ -94,7 +121,7 @@ CompileItem::visit (HIR::ConstantItem &constant) if (flag_name_resolution_2_0) { - auto nr_ctx + auto &nr_ctx = Resolver2_0::ImmutableNameResolutionContext::get ().resolver (); canonical_path @@ -102,18 +129,17 @@ CompileItem::visit (HIR::ConstantItem &constant) } else { - const Resolver::CanonicalPath *canonical_path_ptr = nullptr; - ok = ctx->get_mappings ()->lookup_canonical_path (mappings.get_nodeid (), - &canonical_path_ptr); - rust_assert (ok); - canonical_path = *canonical_path_ptr; + canonical_path = ctx->get_mappings () + .lookup_canonical_path (mappings.get_nodeid ()) + .value (); } - HIR::Expr *const_value_expr = constant.get_expr ().get (); ctx->push_const_context (); tree const_expr - = compile_constant_item (resolved_type, &canonical_path, const_value_expr, - constant.get_locus ()); + = compile_constant_item (mappings.get_hirid (), expr_type, constant_type, + canonical_path, const_value_expr, + constant.get_locus (), + const_value_expr.get_locus ()); ctx->pop_const_context (); ctx->push_const (const_expr); @@ -141,26 +167,44 @@ CompileItem::visit (HIR::Function &function) // is given if (concrete == nullptr) return; - else + + rust_assert (concrete->get_kind () == TyTy::TypeKind::FNDEF); + TyTy::FnType *concrete_fnty = static_cast<TyTy::FnType *> (concrete); + bool is_trait_item_concrete + = ctx->get_mappings () + .lookup_trait_item_defid (concrete_fnty->get_id ()) + .has_value (); + if (!is_trait_item_concrete) { rust_assert (concrete->get_kind () == TyTy::TypeKind::FNDEF); fntype = static_cast<TyTy::FnType *> (concrete); - fntype->monomorphize (); } + else + { + TyTy::BaseType *infer + = Resolver::SubstMapper::InferSubst (fntype, function.get_locus ()); + TyTy::BaseType *resolved + = Resolver::unify_site (function.get_mappings ().get_hirid (), + TyTy::TyWithLocation (infer), + TyTy::TyWithLocation (concrete), + function.get_locus ()); + + rust_assert (resolved->is<TyTy::FnType> ()); + fntype = resolved->as<TyTy::FnType> (); + } + + fntype->monomorphize (); } else { // if this is part of a trait impl block which is not generic we need to // ensure associated types are setup - HirId parent_impl_block = UNKNOWN_HIRID; HirId id = function.get_mappings ().get_hirid (); - HIR::ImplItem *impl_item - = ctx->get_mappings ()->lookup_hir_implitem (id, &parent_impl_block); - if (impl_item != nullptr) + if (auto impl_item = ctx->get_mappings ().lookup_hir_implitem (id)) { Resolver::AssociatedImplTrait *impl = nullptr; bool found = ctx->get_tyctx ()->lookup_associated_trait_impl ( - parent_impl_block, &impl); + impl_item->second, &impl); if (found) impl->setup_raw_associated_types (); } @@ -171,7 +215,7 @@ CompileItem::visit (HIR::Function &function) if (flag_name_resolution_2_0) { - auto nr_ctx + auto &nr_ctx = Resolver2_0::ImmutableNameResolutionContext::get ().resolver (); auto path = nr_ctx.values.to_canonical_path ( @@ -181,10 +225,8 @@ CompileItem::visit (HIR::Function &function) } else { - const Resolver::CanonicalPath *path = nullptr; - bool ok = ctx->get_mappings ()->lookup_canonical_path ( - function.get_mappings ().get_nodeid (), &path); - rust_assert (ok); + auto path = ctx->get_mappings ().lookup_canonical_path ( + function.get_mappings ().get_nodeid ()); canonical_path = *path; } @@ -210,14 +252,17 @@ CompileItem::visit (HIR::Function &function) if (function.get_qualifiers ().is_const ()) ctx->push_const_context (); + auto lookup_root_item = ctx->get_mappings ().lookup_hir_item ( + function.get_mappings ().get_hirid ()); + bool is_root_item = lookup_root_item.has_value (); tree fndecl - = compile_function (function.get_function_name ().as_string (), + = compile_function (is_root_item, + function.get_function_name ().as_string (), function.get_self_param (), function.get_function_params (), function.get_qualifiers (), function.get_visibility (), function.get_outer_attrs (), function.get_locus (), - function.get_definition ().get (), &canonical_path, - fntype); + &function.get_definition (), canonical_path, fntype); reference = address_expression (fndecl, ref_locus); if (function.get_qualifiers ().is_const ()) @@ -229,7 +274,7 @@ CompileItem::visit (HIR::ImplBlock &impl_block) { TyTy::BaseType *self_lookup = nullptr; if (!ctx->get_tyctx ()->lookup_type ( - impl_block.get_type ()->get_mappings ().get_hirid (), &self_lookup)) + impl_block.get_type ().get_mappings ().get_hirid (), &self_lookup)) { rust_error_at (impl_block.get_locus (), "failed to resolve type of impl"); return; diff --git a/gcc/rust/backend/rust-compile-item.h b/gcc/rust/backend/rust-compile-item.h index 1c877fa..59f5d62 100644 --- a/gcc/rust/backend/rust-compile-item.h +++ b/gcc/rust/backend/rust-compile-item.h @@ -31,16 +31,10 @@ protected: public: static tree compile (HIR::Item *item, Context *ctx, TyTy::BaseType *concrete = nullptr, - bool is_query_mode = false, location_t ref_locus = UNDEF_LOCATION) { CompileItem compiler (ctx, concrete, ref_locus); item->accept_vis (compiler); - - if (is_query_mode && compiler.reference == error_mark_node) - rust_internal_error_at (ref_locus, "failed to compile item: %s", - item->as_string ().c_str ()); - return compiler.reference; } diff --git a/gcc/rust/backend/rust-compile-pattern.cc b/gcc/rust/backend/rust-compile-pattern.cc index 1a32f02..121749a 100644 --- a/gcc/rust/backend/rust-compile-pattern.cc +++ b/gcc/rust/backend/rust-compile-pattern.cc @@ -21,6 +21,12 @@ #include "rust-compile-resolve-path.h" #include "rust-constexpr.h" #include "rust-compile-type.h" +#include "print-tree.h" +#include "rust-diagnostics.h" +#include "rust-hir-pattern-abstract.h" +#include "rust-hir-pattern.h" +#include "rust-system.h" +#include "rust-tyty.h" namespace Rust { namespace Compile { @@ -35,11 +41,16 @@ CompilePatternCheckExpr::visit (HIR::PathInExpression &pattern) &lookup); rust_assert (ok); - // this must be an enum - // TODO: might not be + // must be an ADT (?) rust_assert (lookup->get_kind () == TyTy::TypeKind::ADT); TyTy::ADTType *adt = static_cast<TyTy::ADTType *> (lookup); - rust_assert (adt->is_enum ()); + + // if this isn't an enum, always succeed + if (!adt->is_enum ()) + { + check_expr = boolean_true_node; + return; + } // lookup the variant HirId variant_id; @@ -52,17 +63,14 @@ CompilePatternCheckExpr::visit (HIR::PathInExpression &pattern) rust_assert (ok); // find discriminant field of scrutinee - tree scrutinee_record_expr - = Backend::struct_field_expression (match_scrutinee_expr, 0, - pattern.get_locus ()); tree scrutinee_expr_qualifier_expr - = Backend::struct_field_expression (scrutinee_record_expr, 0, + = Backend::struct_field_expression (match_scrutinee_expr, 0, pattern.get_locus ()); // must be enum match_scrutinee_expr = scrutinee_expr_qualifier_expr; - HIR::Expr *discrim_expr = variant->get_discriminant (); + HIR::Expr &discrim_expr = variant->get_discriminant (); tree discrim_expr_node = CompileExpr::Compile (discrim_expr, ctx); check_expr @@ -75,10 +83,9 @@ void CompilePatternCheckExpr::visit (HIR::LiteralPattern &pattern) { // Compile the literal - HIR::LiteralExpr *litexpr - = new HIR::LiteralExpr (pattern.get_mappings (), pattern.get_literal (), - pattern.get_locus (), - std::vector<AST::Attribute> ()); + auto litexpr = std::make_unique<HIR::LiteralExpr> ( + HIR::LiteralExpr (pattern.get_mappings (), pattern.get_literal (), + pattern.get_locus (), std::vector<AST::Attribute> ())); // Note: Floating point literals are currently accepted but will likely be // forbidden in LiteralPatterns in a future version of Rust. @@ -90,7 +97,7 @@ CompilePatternCheckExpr::visit (HIR::LiteralPattern &pattern) rust_sorry_at (pattern.get_locus (), "floating-point literal in pattern"); } - tree lit = CompileExpr::Compile (litexpr, ctx); + tree lit = CompileExpr::Compile (*litexpr, ctx); check_expr = Backend::comparison_expression (ComparisonOperator::EQUAL, match_scrutinee_expr, lit, @@ -98,19 +105,17 @@ CompilePatternCheckExpr::visit (HIR::LiteralPattern &pattern) } static tree -compile_range_pattern_bound (HIR::RangePatternBound *bound, +compile_range_pattern_bound (HIR::RangePatternBound &bound, Analysis::NodeMapping mappings, location_t locus, Context *ctx) { tree result = NULL_TREE; - switch (bound->get_bound_type ()) + switch (bound.get_bound_type ()) { case HIR::RangePatternBound::RangePatternBoundType::LITERAL: { - HIR::RangePatternBoundLiteral &ref - = *static_cast<HIR::RangePatternBoundLiteral *> (bound); + auto &ref = static_cast<HIR::RangePatternBoundLiteral &> (bound); - HIR::LiteralExpr *litexpr - = new HIR::LiteralExpr (mappings, ref.get_literal (), locus, + HIR::LiteralExpr litexpr (mappings, ref.get_literal (), locus, std::vector<AST::Attribute> ()); result = CompileExpr::Compile (litexpr, ctx); @@ -118,8 +123,7 @@ compile_range_pattern_bound (HIR::RangePatternBound *bound, break; case HIR::RangePatternBound::RangePatternBoundType::PATH: { - HIR::RangePatternBoundPath &ref - = *static_cast<HIR::RangePatternBoundPath *> (bound); + auto &ref = static_cast<HIR::RangePatternBoundPath &> (bound); result = ResolvePathRef::Compile (ref.get_path (), ctx); @@ -129,8 +133,7 @@ compile_range_pattern_bound (HIR::RangePatternBound *bound, break; case HIR::RangePatternBound::RangePatternBoundType::QUALPATH: { - HIR::RangePatternBoundQualPath &ref - = *static_cast<HIR::RangePatternBoundQualPath *> (bound); + auto &ref = static_cast<HIR::RangePatternBoundQualPath &> (bound); result = ResolvePathRef::Compile (ref.get_qualified_path (), ctx); @@ -145,10 +148,10 @@ compile_range_pattern_bound (HIR::RangePatternBound *bound, void CompilePatternCheckExpr::visit (HIR::RangePattern &pattern) { - tree upper = compile_range_pattern_bound (pattern.get_upper_bound ().get (), + tree upper = compile_range_pattern_bound (pattern.get_upper_bound (), pattern.get_mappings (), pattern.get_locus (), ctx); - tree lower = compile_range_pattern_bound (pattern.get_lower_bound ().get (), + tree lower = compile_range_pattern_bound (pattern.get_lower_bound (), pattern.get_mappings (), pattern.get_locus (), ctx); @@ -170,7 +173,7 @@ CompilePatternCheckExpr::visit (HIR::ReferencePattern &pattern) { match_scrutinee_expr = indirect_expression (match_scrutinee_expr, pattern.get_locus ()); - pattern.get_referenced_pattern ()->accept_vis (*this); + pattern.get_referenced_pattern ().accept_vis (*this); } void @@ -178,14 +181,13 @@ CompilePatternCheckExpr::visit (HIR::AltPattern &pattern) { auto &alts = pattern.get_alts (); - check_expr = CompilePatternCheckExpr::Compile (alts.at (0).get (), + check_expr = CompilePatternCheckExpr::Compile (*alts.at (0), match_scrutinee_expr, ctx); auto end = alts.end (); for (auto i = alts.begin () + 1; i != end; i++) { tree next_expr - = CompilePatternCheckExpr::Compile (i->get (), match_scrutinee_expr, - ctx); + = CompilePatternCheckExpr::Compile (**i, match_scrutinee_expr, ctx); check_expr = Backend::arithmetic_or_logical_expression ( ArithmeticOrLogicalOperator::BITWISE_OR, check_expr, next_expr, (*i)->get_locus ()); @@ -207,6 +209,7 @@ CompilePatternCheckExpr::visit (HIR::StructPattern &pattern) rust_assert (adt->number_of_variants () > 0); TyTy::VariantDef *variant = nullptr; + tree variant_accesser_expr = nullptr; if (adt->is_enum ()) { // lookup the variant @@ -221,18 +224,21 @@ CompilePatternCheckExpr::visit (HIR::StructPattern &pattern) // find expected discriminant // // need to access qualifier the field, if we use QUAL_UNION_TYPE this - // // would be DECL_QUALIFIER i think. For now this will just access the - // // first record field and its respective qualifier because it will - // // always be set because this is all a big special union - HIR::Expr *discrim_expr = variant->get_discriminant (); + // // would be DECL_QUALIFIER i think. + HIR::Expr &discrim_expr = variant->get_discriminant (); tree discrim_expr_node = CompileExpr::Compile (discrim_expr, ctx); // find discriminant field of scrutinee - tree scrutinee_record_expr - = Backend::struct_field_expression (match_scrutinee_expr, variant_index, - pattern.get_path ().get_locus ()); tree scrutinee_expr_qualifier_expr - = Backend::struct_field_expression (scrutinee_record_expr, 0, + = Backend::struct_field_expression (match_scrutinee_expr, 0, + pattern.get_path ().get_locus ()); + + // access variant data + tree scrutinee_union_expr + = Backend::struct_field_expression (match_scrutinee_expr, 1, + pattern.get_path ().get_locus ()); + variant_accesser_expr + = Backend::struct_field_expression (scrutinee_union_expr, variant_index, pattern.get_path ().get_locus ()); check_expr @@ -241,11 +247,12 @@ CompilePatternCheckExpr::visit (HIR::StructPattern &pattern) discrim_expr_node, pattern.get_path ().get_locus ()); - match_scrutinee_expr = scrutinee_record_expr; + match_scrutinee_expr = scrutinee_expr_qualifier_expr; } else { variant = adt->get_variants ().at (0); + variant_accesser_expr = match_scrutinee_expr; check_expr = boolean_true_node; } @@ -269,19 +276,16 @@ CompilePatternCheckExpr::visit (HIR::StructPattern &pattern) nullptr, &offs); rust_assert (ok); - // we may be offsetting by + 1 here since the first field in the - // record is always the discriminator - offs += adt->is_enum (); tree field_expr - = Backend::struct_field_expression (match_scrutinee_expr, offs, + = Backend::struct_field_expression (variant_accesser_expr, offs, ident.get_locus ()); tree check_expr_sub - = CompilePatternCheckExpr::Compile (ident.get_pattern ().get (), + = CompilePatternCheckExpr::Compile (ident.get_pattern (), field_expr, ctx); check_expr = Backend::arithmetic_or_logical_expression ( ArithmeticOrLogicalOperator::BITWISE_AND, check_expr, - check_expr_sub, ident.get_pattern ()->get_locus ()); + check_expr_sub, ident.get_pattern ().get_locus ()); } break; @@ -296,8 +300,6 @@ CompilePatternCheckExpr::visit (HIR::StructPattern &pattern) void CompilePatternCheckExpr::visit (HIR::TupleStructPattern &pattern) { - size_t tuple_field_index; - // lookup the type TyTy::BaseType *lookup = nullptr; bool ok = ctx->get_tyctx ()->lookup_type ( @@ -308,6 +310,7 @@ CompilePatternCheckExpr::visit (HIR::TupleStructPattern &pattern) rust_assert (lookup->get_kind () == TyTy::TypeKind::ADT); TyTy::ADTType *adt = static_cast<TyTy::ADTType *> (lookup); + int variant_index = 0; rust_assert (adt->number_of_variants () > 0); TyTy::VariantDef *variant = nullptr; if (adt->is_enum ()) @@ -318,20 +321,16 @@ CompilePatternCheckExpr::visit (HIR::TupleStructPattern &pattern) pattern.get_path ().get_mappings ().get_hirid (), &variant_id); rust_assert (ok); - int variant_index = 0; ok = adt->lookup_variant_by_id (variant_id, &variant, &variant_index); rust_assert (ok); // find expected discriminant - HIR::Expr *discrim_expr = variant->get_discriminant (); + HIR::Expr &discrim_expr = variant->get_discriminant (); tree discrim_expr_node = CompileExpr::Compile (discrim_expr, ctx); // find discriminant field of scrutinee - tree scrutinee_record_expr - = Backend::struct_field_expression (match_scrutinee_expr, variant_index, - pattern.get_path ().get_locus ()); tree scrutinee_expr_qualifier_expr - = Backend::struct_field_expression (scrutinee_record_expr, 0, + = Backend::struct_field_expression (match_scrutinee_expr, 0, pattern.get_path ().get_locus ()); check_expr @@ -339,21 +338,15 @@ CompilePatternCheckExpr::visit (HIR::TupleStructPattern &pattern) scrutinee_expr_qualifier_expr, discrim_expr_node, pattern.get_path ().get_locus ()); - - match_scrutinee_expr = scrutinee_record_expr; - // we are offsetting by + 1 here since the first field in the record - // is always the discriminator - tuple_field_index = 1; } else { variant = adt->get_variants ().at (0); check_expr = boolean_true_node; - tuple_field_index = 0; } - std::unique_ptr<HIR::TupleStructItems> &items = pattern.get_items (); - switch (items->get_item_type ()) + HIR::TupleStructItems &items = pattern.get_items (); + switch (items.get_item_type ()) { case HIR::TupleStructItems::RANGED: { // TODO @@ -363,21 +356,30 @@ CompilePatternCheckExpr::visit (HIR::TupleStructPattern &pattern) case HIR::TupleStructItems::MULTIPLE: { HIR::TupleStructItemsNoRange &items_no_range - = static_cast<HIR::TupleStructItemsNoRange &> (*items.get ()); + = static_cast<HIR::TupleStructItemsNoRange &> (items); rust_assert (items_no_range.get_patterns ().size () == variant->num_fields ()); + size_t tuple_field_index = 0; for (auto &pattern : items_no_range.get_patterns ()) { + // find payload union field of scrutinee + tree payload_ref + = Backend::struct_field_expression (match_scrutinee_expr, 1, + pattern->get_locus ()); + + tree variant_ref + = Backend::struct_field_expression (payload_ref, variant_index, + pattern->get_locus ()); + tree field_expr - = Backend::struct_field_expression (match_scrutinee_expr, + = Backend::struct_field_expression (variant_ref, tuple_field_index++, pattern->get_locus ()); tree check_expr_sub - = CompilePatternCheckExpr::Compile (pattern.get (), field_expr, - ctx); + = CompilePatternCheckExpr::Compile (*pattern, field_expr, ctx); check_expr = Backend::arithmetic_or_logical_expression ( ArithmeticOrLogicalOperator::BITWISE_AND, check_expr, check_expr_sub, pattern->get_locus ()); @@ -392,7 +394,7 @@ CompilePatternCheckExpr::visit (HIR::TuplePattern &pattern) { check_expr = boolean_true_node; - switch (pattern.get_items ()->get_item_type ()) + switch (pattern.get_items ().get_item_type ()) { case HIR::TuplePatternItems::RANGED: { // TODO @@ -402,7 +404,7 @@ CompilePatternCheckExpr::visit (HIR::TuplePattern &pattern) case HIR::TuplePatternItems::MULTIPLE: { auto &items = static_cast<HIR::TuplePatternItemsMultiple &> ( - *pattern.get_items ()); + pattern.get_items ()); size_t tuple_field_index = 0; for (auto &pat : items.get_patterns ()) @@ -413,7 +415,7 @@ CompilePatternCheckExpr::visit (HIR::TuplePattern &pattern) pat->get_locus ()); tree check_expr_sub - = CompilePatternCheckExpr::Compile (pat.get (), field_expr, ctx); + = CompilePatternCheckExpr::Compile (*pat, field_expr, ctx); check_expr = Backend::arithmetic_or_logical_expression ( ArithmeticOrLogicalOperator::BITWISE_AND, check_expr, check_expr_sub, pat->get_locus ()); @@ -454,8 +456,8 @@ CompilePatternBindings::visit (HIR::TupleStructPattern &pattern) rust_assert (variant->get_variant_type () == TyTy::VariantDef::VariantType::TUPLE); - std::unique_ptr<HIR::TupleStructItems> &items = pattern.get_items (); - switch (items->get_item_type ()) + HIR::TupleStructItems &items = pattern.get_items (); + switch (items.get_item_type ()) { case HIR::TupleStructItems::RANGED: { // TODO @@ -465,20 +467,22 @@ CompilePatternBindings::visit (HIR::TupleStructPattern &pattern) case HIR::TupleStructItems::MULTIPLE: { HIR::TupleStructItemsNoRange &items_no_range - = static_cast<HIR::TupleStructItemsNoRange &> (*items.get ()); + = static_cast<HIR::TupleStructItemsNoRange &> (items); rust_assert (items_no_range.get_patterns ().size () == variant->num_fields ()); if (adt->is_enum ()) { - // we are offsetting by + 1 here since the first field in the record - // is always the discriminator - size_t tuple_field_index = 1; + size_t tuple_field_index = 0; for (auto &pattern : items_no_range.get_patterns ()) { + tree payload_accessor_union + = Backend::struct_field_expression (match_scrutinee_expr, 1, + pattern->get_locus ()); + tree variant_accessor - = Backend::struct_field_expression (match_scrutinee_expr, + = Backend::struct_field_expression (payload_accessor_union, variant_index, pattern->get_locus ()); @@ -487,8 +491,7 @@ CompilePatternBindings::visit (HIR::TupleStructPattern &pattern) tuple_field_index++, pattern->get_locus ()); - ctx->insert_pattern_binding ( - pattern->get_mappings ().get_hirid (), binding); + CompilePatternBindings::Compile (*pattern, binding, ctx); } } else @@ -503,8 +506,7 @@ CompilePatternBindings::visit (HIR::TupleStructPattern &pattern) tuple_field_index++, pattern->get_locus ()); - ctx->insert_pattern_binding ( - pattern->get_mappings ().get_hirid (), binding); + CompilePatternBindings::Compile (*pattern, binding, ctx); } } } @@ -512,6 +514,71 @@ CompilePatternBindings::visit (HIR::TupleStructPattern &pattern) } } +tree +CompilePatternBindings::make_struct_access (TyTy::ADTType *adt, + TyTy::VariantDef *variant, + const Identifier &ident, + int variant_index) +{ + size_t offs = 0; + auto ok = variant->lookup_field (ident.as_string (), nullptr, &offs); + rust_assert (ok); + + if (adt->is_enum ()) + { + tree payload_accessor_union + = Backend::struct_field_expression (match_scrutinee_expr, 1, + ident.get_locus ()); + + tree variant_accessor + = Backend::struct_field_expression (payload_accessor_union, + variant_index, ident.get_locus ()); + + return Backend::struct_field_expression (variant_accessor, offs, + ident.get_locus ()); + } + else + { + tree variant_accessor = match_scrutinee_expr; + + return Backend::struct_field_expression (variant_accessor, offs, + ident.get_locus ()); + } +} + +void +CompilePatternBindings::handle_struct_pattern_ident ( + HIR::StructPatternField &pat, TyTy::ADTType *adt, TyTy::VariantDef *variant, + int variant_index) +{ + HIR::StructPatternFieldIdent &ident + = static_cast<HIR::StructPatternFieldIdent &> (pat); + + auto identifier = ident.get_identifier (); + tree binding = make_struct_access (adt, variant, identifier, variant_index); + + ctx->insert_pattern_binding (ident.get_mappings ().get_hirid (), binding); +} + +void +CompilePatternBindings::handle_struct_pattern_ident_pat ( + HIR::StructPatternField &pat, TyTy::ADTType *adt, TyTy::VariantDef *variant, + int variant_index) +{ + auto &pattern = static_cast<HIR::StructPatternFieldIdentPat &> (pat); + + tree binding = make_struct_access (adt, variant, pattern.get_identifier (), + variant_index); + CompilePatternBindings::Compile (pattern.get_pattern (), binding, ctx); +} + +void +CompilePatternBindings::handle_struct_pattern_tuple_pat ( + HIR::StructPatternField &pat) +{ + rust_unreachable (); +} + void CompilePatternBindings::visit (HIR::StructPattern &pattern) { @@ -547,52 +614,14 @@ CompilePatternBindings::visit (HIR::StructPattern &pattern) { switch (field->get_item_type ()) { - case HIR::StructPatternField::ItemType::TUPLE_PAT: { - // TODO - rust_unreachable (); - } + case HIR::StructPatternField::ItemType::TUPLE_PAT: + handle_struct_pattern_tuple_pat (*field); break; - - case HIR::StructPatternField::ItemType::IDENT_PAT: { - // TODO - rust_unreachable (); - } + case HIR::StructPatternField::ItemType::IDENT_PAT: + handle_struct_pattern_ident_pat (*field, adt, variant, variant_index); break; - - case HIR::StructPatternField::ItemType::IDENT: { - HIR::StructPatternFieldIdent &ident - = static_cast<HIR::StructPatternFieldIdent &> (*field.get ()); - - size_t offs = 0; - ok = variant->lookup_field (ident.get_identifier ().as_string (), - nullptr, &offs); - rust_assert (ok); - - tree binding = error_mark_node; - if (adt->is_enum ()) - { - tree variant_accessor - = Backend::struct_field_expression (match_scrutinee_expr, - variant_index, - ident.get_locus ()); - - // we are offsetting by + 1 here since the first field in the - // record is always the discriminator - binding = Backend::struct_field_expression (variant_accessor, - offs + 1, - ident.get_locus ()); - } - else - { - tree variant_accessor = match_scrutinee_expr; - binding - = Backend::struct_field_expression (variant_accessor, offs, - ident.get_locus ()); - } - - ctx->insert_pattern_binding (ident.get_mappings ().get_hirid (), - binding); - } + case HIR::StructPatternField::ItemType::IDENT: + handle_struct_pattern_ident (*field, adt, variant, variant_index); break; } } @@ -604,18 +633,112 @@ CompilePatternBindings::visit (HIR::ReferencePattern &pattern) tree derefed = indirect_expression (match_scrutinee_expr, pattern.get_locus ()); - CompilePatternBindings::Compile (pattern.get_referenced_pattern ().get (), - derefed, ctx); + CompilePatternBindings::Compile (pattern.get_referenced_pattern (), derefed, + ctx); } void CompilePatternBindings::visit (HIR::IdentifierPattern &pattern) { - ctx->insert_pattern_binding (pattern.get_mappings ().get_hirid (), - match_scrutinee_expr); + if (!pattern.get_is_ref ()) + { + ctx->insert_pattern_binding (pattern.get_mappings ().get_hirid (), + match_scrutinee_expr); + return; + } + + tree ref = address_expression (match_scrutinee_expr, + EXPR_LOCATION (match_scrutinee_expr)); + ctx->insert_pattern_binding (pattern.get_mappings ().get_hirid (), ref); } void +CompilePatternBindings::visit (HIR::TuplePattern &pattern) +{ + rust_assert (pattern.has_tuple_pattern_items ()); + + // lookup the type + TyTy::BaseType *ty = nullptr; + bool ok + = ctx->get_tyctx ()->lookup_type (pattern.get_mappings ().get_hirid (), + &ty); + rust_assert (ok); + + switch (pattern.get_items ().get_item_type ()) + { + case HIR::TuplePatternItems::ItemType::RANGED: { + size_t tuple_idx = 0; + auto &items + = static_cast<HIR::TuplePatternItemsRanged &> (pattern.get_items ()); + + auto &items_lower = items.get_lower_patterns (); + auto &items_upper = items.get_upper_patterns (); + + for (auto &sub : items_lower) + { + TyTy::BaseType *ty_sub = nullptr; + HirId sub_id = sub->get_mappings ().get_hirid (); + bool ok = ctx->get_tyctx ()->lookup_type (sub_id, &ty_sub); + rust_assert (ok); + + tree sub_init + = Backend::struct_field_expression (match_scrutinee_expr, + tuple_idx, sub->get_locus ()); + + CompilePatternBindings::Compile (*sub.get (), sub_init, ctx); + tuple_idx++; + } + + rust_assert (ty->get_kind () == TyTy::TypeKind::TUPLE); + tuple_idx = static_cast<TyTy::TupleType &> (*ty).num_fields () + - items_upper.size (); + + for (auto &sub : items_upper) + { + TyTy::BaseType *ty_sub = nullptr; + HirId sub_id = sub->get_mappings ().get_hirid (); + bool ok = ctx->get_tyctx ()->lookup_type (sub_id, &ty_sub); + rust_assert (ok); + + tree sub_init + = Backend::struct_field_expression (match_scrutinee_expr, + tuple_idx, sub->get_locus ()); + CompilePatternBindings::Compile (*sub.get (), sub_init, ctx); + tuple_idx++; + } + + return; + } + case HIR::TuplePatternItems::ItemType::MULTIPLE: { + size_t tuple_idx = 0; + auto &items = static_cast<HIR::TuplePatternItemsMultiple &> ( + pattern.get_items ()); + + for (auto &sub : items.get_patterns ()) + { + TyTy::BaseType *ty_sub = nullptr; + HirId sub_id = sub->get_mappings ().get_hirid (); + bool ok = ctx->get_tyctx ()->lookup_type (sub_id, &ty_sub); + rust_assert (ok); + + tree sub_init + = Backend::struct_field_expression (match_scrutinee_expr, + tuple_idx, sub->get_locus ()); + CompilePatternBindings::Compile (*sub.get (), sub_init, ctx); + tuple_idx++; + } + + return; + } + default: { + rust_unreachable (); + } + } +} + +// + +void CompilePatternLet::visit (HIR::IdentifierPattern &pattern) { Bvariable *var = nullptr; @@ -627,7 +750,7 @@ CompilePatternLet::visit (HIR::IdentifierPattern &pattern) { ctx->add_statement (init_expr); - auto unit_type_init_expr = unit_expression (ctx, rval_locus); + auto unit_type_init_expr = unit_expression (rval_locus); auto s = Backend::init_statement (fnctx.fndecl, var, unit_type_init_expr); ctx->add_statement (s); } @@ -665,12 +788,12 @@ CompilePatternLet::visit (HIR::TuplePattern &pattern) tree access_expr = Backend::var_expression (tmp_var, pattern.get_locus ()); ctx->add_statement (init_stmt); - switch (pattern.get_items ()->get_item_type ()) + switch (pattern.get_items ().get_item_type ()) { case HIR::TuplePatternItems::ItemType::RANGED: { size_t tuple_idx = 0; auto &items - = static_cast<HIR::TuplePatternItemsRanged &> (*pattern.get_items ()); + = static_cast<HIR::TuplePatternItemsRanged &> (pattern.get_items ()); auto &items_lower = items.get_lower_patterns (); auto &items_upper = items.get_upper_patterns (); @@ -714,7 +837,7 @@ CompilePatternLet::visit (HIR::TuplePattern &pattern) case HIR::TuplePatternItems::ItemType::MULTIPLE: { size_t tuple_idx = 0; auto &items = static_cast<HIR::TuplePatternItemsMultiple &> ( - *pattern.get_items ()); + pattern.get_items ()); for (auto &sub : items.get_patterns ()) { diff --git a/gcc/rust/backend/rust-compile-pattern.h b/gcc/rust/backend/rust-compile-pattern.h index 17c82fa..32b6db2 100644 --- a/gcc/rust/backend/rust-compile-pattern.h +++ b/gcc/rust/backend/rust-compile-pattern.h @@ -17,7 +17,9 @@ // <http://www.gnu.org/licenses/>. #include "rust-compile-base.h" +#include "rust-hir-pattern.h" #include "rust-hir-visitor.h" +#include "rust-tyty.h" namespace Rust { namespace Compile { @@ -26,11 +28,11 @@ class CompilePatternCheckExpr : public HIRCompileBase, public HIR::HIRPatternVisitor { public: - static tree Compile (HIR::Pattern *pattern, tree match_scrutinee_expr, + static tree Compile (HIR::Pattern &pattern, tree match_scrutinee_expr, Context *ctx) { CompilePatternCheckExpr compiler (ctx, match_scrutinee_expr); - pattern->accept_vis (compiler); + pattern.accept_vis (compiler); rust_assert (compiler.check_expr); return compiler.check_expr; } @@ -71,17 +73,31 @@ class CompilePatternBindings : public HIRCompileBase, public HIR::HIRPatternVisitor { public: - static void Compile (HIR::Pattern *pattern, tree match_scrutinee_expr, + static void Compile (HIR::Pattern &pattern, tree match_scrutinee_expr, Context *ctx) { CompilePatternBindings compiler (ctx, match_scrutinee_expr); - pattern->accept_vis (compiler); + pattern.accept_vis (compiler); } + tree make_struct_access (TyTy::ADTType *adt, TyTy::VariantDef *variant, + const Identifier &ident, int variant_index); + + void handle_struct_pattern_ident (HIR::StructPatternField &pat, + TyTy::ADTType *adt, + TyTy::VariantDef *variant, + int variant_index); + void handle_struct_pattern_ident_pat (HIR::StructPatternField &pat, + TyTy::ADTType *adt, + TyTy::VariantDef *variant, + int variant_index); + void handle_struct_pattern_tuple_pat (HIR::StructPatternField &pat); + void visit (HIR::StructPattern &pattern) override; void visit (HIR::TupleStructPattern &pattern) override; void visit (HIR::ReferencePattern &pattern) override; void visit (HIR::IdentifierPattern &) override; + void visit (HIR::TuplePattern &pattern) override; // Empty visit for unused Pattern HIR nodes. void visit (HIR::AltPattern &) override {} @@ -90,7 +106,6 @@ public: void visit (HIR::QualifiedPathInExpression &) override {} void visit (HIR::RangePattern &) override {} void visit (HIR::SlicePattern &) override {} - void visit (HIR::TuplePattern &) override {} void visit (HIR::WildcardPattern &) override {} protected: diff --git a/gcc/rust/backend/rust-compile-resolve-path.cc b/gcc/rust/backend/rust-compile-resolve-path.cc index 3bb45a5..9783642 100644 --- a/gcc/rust/backend/rust-compile-resolve-path.cc +++ b/gcc/rust/backend/rust-compile-resolve-path.cc @@ -32,18 +32,41 @@ namespace Rust { namespace Compile { -void -ResolvePathRef::visit (HIR::QualifiedPathInExpression &expr) +tree +ResolvePathRef::Compile (HIR::QualifiedPathInExpression &expr, Context *ctx) { - resolved = resolve (expr.get_final_segment ().get_segment (), - expr.get_mappings (), expr.get_locus (), true); + ResolvePathRef resolver (ctx); + return resolver.resolve_path_like (expr); } -void -ResolvePathRef::visit (HIR::PathInExpression &expr) +tree +ResolvePathRef::Compile (HIR::PathInExpression &expr, Context *ctx) { - resolved = resolve (expr.get_final_segment ().get_segment (), - expr.get_mappings (), expr.get_locus (), false); + ResolvePathRef resolver (ctx); + return resolver.resolve_path_like (expr); +} + +ResolvePathRef::ResolvePathRef (Context *ctx) : HIRCompileBase (ctx) {} + +template <typename T> +tree +ResolvePathRef::resolve_path_like (T &expr) +{ + if (expr.is_lang_item ()) + { + auto lang_item + = Analysis::Mappings::get ().get_lang_item_node (expr.get_lang_item ()); + + // FIXME: Is that correct? :/ + auto final_segment + = HIR::PathIdentSegment (LangItem::ToString (expr.get_lang_item ())); + + return resolve_with_node_id (final_segment, expr.get_mappings (), + expr.get_locus (), true, lang_item); + } + + return resolve (expr.get_final_segment ().get_segment (), + expr.get_mappings (), expr.get_locus (), true); } tree @@ -57,7 +80,7 @@ ResolvePathRef::attempt_constructor_expression_lookup ( TyTy::ADTType *adt = static_cast<TyTy::ADTType *> (lookup); if (adt->is_unit ()) - return unit_expression (ctx, expr_locus); + return unit_expression (expr_locus); if (!adt->is_enum ()) return error_mark_node; @@ -81,56 +104,36 @@ ResolvePathRef::attempt_constructor_expression_lookup ( tree compiled_adt_type = TyTyResolveCompile::compile (ctx, adt); // make the ctor for the union - HIR::Expr *discrim_expr = variant->get_discriminant (); + HIR::Expr &discrim_expr = variant->get_discriminant (); + ctx->push_const_context (); tree discrim_expr_node = CompileExpr::Compile (discrim_expr, ctx); + ctx->pop_const_context (); tree folded_discrim_expr = fold_expr (discrim_expr_node); tree qualifier = folded_discrim_expr; - return Backend::constructor_expression (compiled_adt_type, true, {qualifier}, - union_disriminator, expr_locus); + // false for is enum but this is an enum but we have a new layout + return Backend::constructor_expression (compiled_adt_type, false, {qualifier}, + -1, expr_locus); } tree -ResolvePathRef::resolve (const HIR::PathIdentSegment &final_segment, - const Analysis::NodeMapping &mappings, - location_t expr_locus, bool is_qualified_path) +ResolvePathRef::resolve_with_node_id ( + const HIR::PathIdentSegment &final_segment, + const Analysis::NodeMapping &mappings, location_t expr_locus, + bool is_qualified_path, NodeId resolved_node_id) { TyTy::BaseType *lookup = nullptr; bool ok = ctx->get_tyctx ()->lookup_type (mappings.get_hirid (), &lookup); rust_assert (ok); - // need to look up the reference for this identifier - - // this can fail because it might be a Constructor for something - // in that case the caller should attempt ResolvePathType::Compile - NodeId ref_node_id = UNKNOWN_NODEID; - if (flag_name_resolution_2_0) - { - auto nr_ctx - = Resolver2_0::ImmutableNameResolutionContext::get ().resolver (); - - auto resolved = nr_ctx.lookup (mappings.get_nodeid ()); - - if (!resolved) - return attempt_constructor_expression_lookup (lookup, ctx, mappings, - expr_locus); - - ref_node_id = *resolved; - } - else - { - if (!ctx->get_resolver ()->lookup_resolved_name (mappings.get_nodeid (), - &ref_node_id)) - return attempt_constructor_expression_lookup (lookup, ctx, mappings, - expr_locus); - } - - HirId ref; - if (!ctx->get_mappings ()->lookup_node_to_hir (ref_node_id, &ref)) + tl::optional<HirId> hid + = ctx->get_mappings ().lookup_node_to_hir (resolved_node_id); + if (!hid.has_value ()) { rust_error_at (expr_locus, "reverse call path lookup failure"); return error_mark_node; } + auto ref = hid.value (); // might be a constant tree constant_expr; @@ -183,6 +186,11 @@ ResolvePathRef::resolve (const HIR::PathIdentSegment &final_segment, } } + // Handle unit struct + if (lookup->get_kind () == TyTy::TypeKind::ADT) + return attempt_constructor_expression_lookup (lookup, ctx, mappings, + expr_locus); + // let the query system figure it out tree resolved_item = query_compile (ref, lookup, final_segment, mappings, expr_locus, is_qualified_path); @@ -190,39 +198,73 @@ ResolvePathRef::resolve (const HIR::PathIdentSegment &final_segment, { TREE_USED (resolved_item) = 1; } + return resolved_item; } tree +ResolvePathRef::resolve (const HIR::PathIdentSegment &final_segment, + const Analysis::NodeMapping &mappings, + location_t expr_locus, bool is_qualified_path) +{ + TyTy::BaseType *lookup = nullptr; + bool ok = ctx->get_tyctx ()->lookup_type (mappings.get_hirid (), &lookup); + rust_assert (ok); + + // need to look up the reference for this identifier + + // this can fail because it might be a Constructor for something + // in that case the caller should attempt ResolvePathType::Compile + NodeId ref_node_id = UNKNOWN_NODEID; + if (flag_name_resolution_2_0) + { + auto &nr_ctx + = Resolver2_0::ImmutableNameResolutionContext::get ().resolver (); + + auto resolved = nr_ctx.lookup (mappings.get_nodeid ()); + + if (!resolved) + return attempt_constructor_expression_lookup (lookup, ctx, mappings, + expr_locus); + + ref_node_id = *resolved; + } + else + { + if (!ctx->get_resolver ()->lookup_resolved_name (mappings.get_nodeid (), + &ref_node_id)) + return attempt_constructor_expression_lookup (lookup, ctx, mappings, + expr_locus); + } + + return resolve_with_node_id (final_segment, mappings, expr_locus, + is_qualified_path, ref_node_id); +} + +tree HIRCompileBase::query_compile (HirId ref, TyTy::BaseType *lookup, const HIR::PathIdentSegment &final_segment, const Analysis::NodeMapping &mappings, location_t expr_locus, bool is_qualified_path) { - HIR::Item *resolved_item = ctx->get_mappings ()->lookup_hir_item (ref); - HirId parent_block; - HIR::ExternalItem *resolved_extern_item - = ctx->get_mappings ()->lookup_hir_extern_item (ref, &parent_block); - bool is_hir_item = resolved_item != nullptr; - bool is_hir_extern_item = resolved_extern_item != nullptr; bool is_fn = lookup->get_kind () == TyTy::TypeKind::FNDEF; - if (is_hir_item) + if (auto resolved_item = ctx->get_mappings ().lookup_hir_item (ref)) { if (!lookup->has_substitutions_defined ()) - return CompileItem::compile (resolved_item, ctx, nullptr, true, - expr_locus); + return CompileItem::compile (*resolved_item, ctx, nullptr, expr_locus); else - return CompileItem::compile (resolved_item, ctx, lookup, true, - expr_locus); + return CompileItem::compile (*resolved_item, ctx, lookup, expr_locus); } - else if (is_hir_extern_item) + else if (auto hir_extern_item + = ctx->get_mappings ().lookup_hir_extern_item (ref)) { + HIR::ExternalItem *resolved_extern_item = hir_extern_item->first; if (!lookup->has_substitutions_defined ()) return CompileExternItem::compile (resolved_extern_item, ctx, nullptr, - true, expr_locus); + expr_locus); else return CompileExternItem::compile (resolved_extern_item, ctx, lookup, - true, expr_locus); + expr_locus); } else { @@ -240,26 +282,20 @@ HIRCompileBase::query_compile (HirId ref, TyTy::BaseType *lookup, } } - HirId parent_impl_id = UNKNOWN_HIRID; - HIR::ImplItem *resolved_item - = ctx->get_mappings ()->lookup_hir_implitem (ref, &parent_impl_id); - bool is_impl_item = resolved_item != nullptr; - if (is_impl_item) + if (auto resolved_item = ctx->get_mappings ().lookup_hir_implitem (ref)) { if (!lookup->has_substitutions_defined ()) - return CompileInherentImplItem::Compile (resolved_item, ctx, - nullptr, true, expr_locus); + return CompileInherentImplItem::Compile (resolved_item->first, ctx, + nullptr, expr_locus); else - return CompileInherentImplItem::Compile (resolved_item, ctx, lookup, - true, expr_locus); + return CompileInherentImplItem::Compile (resolved_item->first, ctx, + lookup, expr_locus); } - else + else if (auto trait_item + = ctx->get_mappings ().lookup_hir_trait_item (ref)) { - // it might be resolved to a trait item - HIR::TraitItem *trait_item - = ctx->get_mappings ()->lookup_hir_trait_item (ref); - HIR::Trait *trait = ctx->get_mappings ()->lookup_trait_item_mapping ( - trait_item->get_mappings ().get_hirid ()); + HIR::Trait *trait = ctx->get_mappings ().lookup_trait_item_mapping ( + trait_item.value ()->get_mappings ().get_hirid ()); Resolver::TraitReference *trait_ref = &Resolver::TraitReference::error_node (); @@ -267,16 +303,41 @@ HIRCompileBase::query_compile (HirId ref, TyTy::BaseType *lookup, trait->get_mappings ().get_defid (), &trait_ref); rust_assert (ok); - TyTy::BaseType *receiver = nullptr; - ok = ctx->get_tyctx ()->lookup_receiver (mappings.get_hirid (), - &receiver); - rust_assert (ok); - receiver = receiver->destructure (); + if (trait_item.value ()->get_item_kind () + == HIR::TraitItem::TraitItemKind::CONST) + { + auto &c + = *static_cast<HIR::TraitItemConst *> (trait_item.value ()); + if (!c.has_expr ()) + { + rich_location r (line_table, expr_locus); + r.add_range (trait->get_locus ()); + r.add_range (c.get_locus ()); + rust_error_at (r, "no default expression on trait constant"); + return error_mark_node; + } + + return CompileExpr::Compile (c.get_expr (), ctx); + } + + if (trait_item.value ()->get_item_kind () + != HIR::TraitItem::TraitItemKind::FUNC) + return error_mark_node; // the type resolver can only resolve type bounds to their trait // item so its up to us to figure out if this path should resolve // to an trait-impl-block-item or if it can be defaulted to the // trait-impl-item's definition + // + // because we know this is resolved to a trait item we can actually + // just grab the Self type parameter here for the receiver to match + // the appropriate impl block + + rust_assert (lookup->is<TyTy::FnType> ()); + auto fn = lookup->as<TyTy::FnType> (); + rust_assert (fn->get_num_type_params () > 0); + auto &self = fn->get_substs ().at (0); + auto receiver = self.get_param_ty (); auto candidates = Resolver::PathProbeImplTrait::Probe (receiver, final_segment, trait_ref); @@ -285,7 +346,7 @@ HIRCompileBase::query_compile (HirId ref, TyTy::BaseType *lookup, // this means we are defaulting back to the trait_item if // possible Resolver::TraitItemReference *trait_item_ref = nullptr; - bool ok = trait_ref->lookup_hir_trait_item (*trait_item, + bool ok = trait_ref->lookup_hir_trait_item (*trait_item.value (), &trait_item_ref); rust_assert (ok); // found rust_assert (trait_item_ref->is_optional ()); // has definition @@ -306,16 +367,15 @@ HIRCompileBase::query_compile (HirId ref, TyTy::BaseType *lookup, TyTy::BaseType *self = nullptr; bool ok = ctx->get_tyctx ()->lookup_type ( - impl->get_type ()->get_mappings ().get_hirid (), &self); + impl->get_type ().get_mappings ().get_hirid (), &self); rust_assert (ok); if (!lookup->has_substitutions_defined ()) return CompileInherentImplItem::Compile (impl_item, ctx, - nullptr, true, - expr_locus); + nullptr, expr_locus); else return CompileInherentImplItem::Compile (impl_item, ctx, lookup, - true, expr_locus); + expr_locus); } } } diff --git a/gcc/rust/backend/rust-compile-resolve-path.h b/gcc/rust/backend/rust-compile-resolve-path.h index a920fcc..b0713ab 100644 --- a/gcc/rust/backend/rust-compile-resolve-path.h +++ b/gcc/rust/backend/rust-compile-resolve-path.h @@ -20,53 +20,39 @@ #define RUST_COMPILE_RESOLVE_PATH #include "rust-compile-base.h" -#include "rust-hir-visitor.h" namespace Rust { namespace Compile { -class ResolvePathRef : public HIRCompileBase, public HIR::HIRPatternVisitor +class ResolvePathRef : public HIRCompileBase { public: - static tree Compile (HIR::QualifiedPathInExpression &expr, Context *ctx) - { - ResolvePathRef resolver (ctx); - expr.accept_vis (resolver); - return resolver.resolved; - } - - static tree Compile (HIR::PathInExpression &expr, Context *ctx) - { - ResolvePathRef resolver (ctx); - expr.accept_vis (resolver); - return resolver.resolved; - } - - void visit (HIR::PathInExpression &expr) override; - void visit (HIR::QualifiedPathInExpression &expr) override; - - // Empty visit for unused Pattern HIR nodes. - void visit (HIR::IdentifierPattern &) override {} - void visit (HIR::LiteralPattern &) override {} - void visit (HIR::RangePattern &) override {} - void visit (HIR::ReferencePattern &) override {} - void visit (HIR::SlicePattern &) override {} - void visit (HIR::AltPattern &) override {} - void visit (HIR::StructPattern &) override {} - void visit (HIR::TuplePattern &) override {} - void visit (HIR::TupleStructPattern &) override {} - void visit (HIR::WildcardPattern &) override {} - - ResolvePathRef (Context *ctx) - : HIRCompileBase (ctx), resolved (error_mark_node) - {} - + static tree Compile (HIR::QualifiedPathInExpression &expr, Context *ctx); + + static tree Compile (HIR::PathInExpression &expr, Context *ctx); + + ResolvePathRef (Context *ctx); + + /** + * Generic visitor for both PathInExpression and QualifiedPathInExpression + */ + template <typename T> tree resolve_path_like (T &expr); + + /** + * Inner implementation of `resolve` - resolution with an already known NodeId + */ + tree resolve_with_node_id (const HIR::PathIdentSegment &final_segment, + const Analysis::NodeMapping &mappings, + location_t locus, bool is_qualified_path, + NodeId resolved_node_id); + /** + * Resolve a mappings' NodeId and call into `resolve_with_node_id` which + * performs the rest of the path resolution + */ tree resolve (const HIR::PathIdentSegment &final_segment, const Analysis::NodeMapping &mappings, location_t locus, bool is_qualified_path); - tree resolved; - private: tree attempt_constructor_expression_lookup (TyTy::BaseType *lookup, Context *ctx, diff --git a/gcc/rust/backend/rust-compile-stmt.cc b/gcc/rust/backend/rust-compile-stmt.cc index e7ba370..023c2c8 100644 --- a/gcc/rust/backend/rust-compile-stmt.cc +++ b/gcc/rust/backend/rust-compile-stmt.cc @@ -40,13 +40,13 @@ CompileStmt::Compile (HIR::Stmt *stmt, Context *ctx) void CompileStmt::visit (HIR::ExprStmt &stmt) { - translated = CompileExpr::Compile (stmt.get_expr ().get (), ctx); + translated = CompileExpr::Compile (stmt.get_expr (), ctx); } void CompileStmt::visit (HIR::LetStmt &stmt) { - HIR::Pattern &stmt_pattern = *stmt.get_pattern (); + HIR::Pattern &stmt_pattern = stmt.get_pattern (); HirId stmt_id = stmt_pattern.get_mappings ().get_hirid (); TyTy::BaseType *ty = nullptr; @@ -68,7 +68,7 @@ CompileStmt::visit (HIR::LetStmt &stmt) if (!stmt.has_init_expr ()) return; - tree init = CompileExpr::Compile (stmt.get_init_expr ().get (), ctx); + tree init = CompileExpr::Compile (stmt.get_init_expr (), ctx); // FIXME use error_mark_node, check that CompileExpr returns error_mark_node // on failure and make this an assertion if (init == nullptr) @@ -76,11 +76,11 @@ CompileStmt::visit (HIR::LetStmt &stmt) TyTy::BaseType *actual = nullptr; bool ok = ctx->get_tyctx ()->lookup_type ( - stmt.get_init_expr ()->get_mappings ().get_hirid (), &actual); + stmt.get_init_expr ().get_mappings ().get_hirid (), &actual); rust_assert (ok); - location_t lvalue_locus = stmt.get_pattern ()->get_locus (); - location_t rvalue_locus = stmt.get_init_expr ()->get_locus (); + location_t lvalue_locus = stmt.get_pattern ().get_locus (); + location_t rvalue_locus = stmt.get_init_expr ().get_locus (); TyTy::BaseType *expected = ty; init = coercion_site (stmt.get_mappings ().get_hirid (), init, actual, expected, lvalue_locus, rvalue_locus); diff --git a/gcc/rust/backend/rust-compile-struct-field-expr.cc b/gcc/rust/backend/rust-compile-struct-field-expr.cc index d642e28..e10ea57 100644 --- a/gcc/rust/backend/rust-compile-struct-field-expr.cc +++ b/gcc/rust/backend/rust-compile-struct-field-expr.cc @@ -27,22 +27,22 @@ CompileStructExprField::CompileStructExprField (Context *ctx) {} tree -CompileStructExprField::Compile (HIR::StructExprField *field, Context *ctx) +CompileStructExprField::Compile (HIR::StructExprField &field, Context *ctx) { CompileStructExprField compiler (ctx); - switch (field->get_kind ()) + switch (field.get_kind ()) { case HIR::StructExprField::StructExprFieldKind::IDENTIFIER: - compiler.visit (static_cast<HIR::StructExprFieldIdentifier &> (*field)); + compiler.visit (static_cast<HIR::StructExprFieldIdentifier &> (field)); break; case HIR::StructExprField::StructExprFieldKind::IDENTIFIER_VALUE: compiler.visit ( - static_cast<HIR::StructExprFieldIdentifierValue &> (*field)); + static_cast<HIR::StructExprFieldIdentifierValue &> (field)); break; case HIR::StructExprField::StructExprFieldKind::INDEX_VALUE: - compiler.visit (static_cast<HIR::StructExprFieldIndexValue &> (*field)); + compiler.visit (static_cast<HIR::StructExprFieldIndexValue &> (field)); break; } return compiler.translated; @@ -51,13 +51,13 @@ CompileStructExprField::Compile (HIR::StructExprField *field, Context *ctx) void CompileStructExprField::visit (HIR::StructExprFieldIdentifierValue &field) { - translated = CompileExpr::Compile (field.get_value ().get (), ctx); + translated = CompileExpr::Compile (field.get_value (), ctx); } void CompileStructExprField::visit (HIR::StructExprFieldIndexValue &field) { - translated = CompileExpr::Compile (field.get_value ().get (), ctx); + translated = CompileExpr::Compile (field.get_value (), ctx); } void @@ -74,7 +74,7 @@ CompileStructExprField::visit (HIR::StructExprFieldIdentifier &field) HIR::GenericArgs::create_empty ()); HIR::PathInExpression expr (mappings_copy2, {seg}, field.get_locus (), false, {}); - translated = CompileExpr::Compile (&expr, ctx); + translated = CompileExpr::Compile (expr, ctx); } } // namespace Compile diff --git a/gcc/rust/backend/rust-compile-struct-field-expr.h b/gcc/rust/backend/rust-compile-struct-field-expr.h index 1ee4d1b..af1f367 100644 --- a/gcc/rust/backend/rust-compile-struct-field-expr.h +++ b/gcc/rust/backend/rust-compile-struct-field-expr.h @@ -27,7 +27,7 @@ namespace Compile { class CompileStructExprField : private HIRCompileBase { public: - static tree Compile (HIR::StructExprField *field, Context *ctx); + static tree Compile (HIR::StructExprField &field, Context *ctx); protected: void visit (HIR::StructExprFieldIdentifierValue &field); diff --git a/gcc/rust/backend/rust-compile-type.cc b/gcc/rust/backend/rust-compile-type.cc index 0a3ba35..5ca1d82 100644 --- a/gcc/rust/backend/rust-compile-type.cc +++ b/gcc/rust/backend/rust-compile-type.cc @@ -22,6 +22,7 @@ #include "rust-gcc.h" #include "tree.h" +#include "stor-layout.h" namespace Rust { namespace Compile { @@ -54,7 +55,7 @@ TyTyResolveCompile::compile (Context *ctx, const TyTy::BaseType *ty, // see: gcc/c/c-decl.cc:8230-8241 // https://github.com/Rust-GCC/gccrs/blob/0024bc2f028369b871a65ceb11b2fddfb0f9c3aa/gcc/c/c-decl.c#L8229-L8241 tree -TyTyResolveCompile::get_implicit_enumeral_node_type (Context *ctx) +TyTyResolveCompile::get_implicit_enumeral_node_type (TyTy::BaseType *repr) { // static tree enum_node = NULL_TREE; // if (enum_node == NULL_TREE) @@ -76,15 +77,7 @@ TyTyResolveCompile::get_implicit_enumeral_node_type (Context *ctx) // } // return enum_node; - static tree enum_node = NULL_TREE; - if (enum_node == NULL_TREE) - { - // equivalent to isize - enum_node = Backend::named_type ( - "enumeral", Backend::integer_type (false, Backend::get_pointer_size ()), - BUILTINS_LOCATION); - } - return enum_node; + return compile (ctx, repr); } tree @@ -93,8 +86,17 @@ TyTyResolveCompile::get_unit_type (Context *ctx) static tree unit_type; if (unit_type == nullptr) { + auto cn = ctx->get_mappings ().get_current_crate (); + auto &c = ctx->get_mappings ().get_ast_crate (cn); + location_t locus = BUILTINS_LOCATION; + if (c.items.size () > 0) + { + auto &item = c.items[0]; + locus = item->get_locus (); + } + auto unit_type_node = Backend::struct_type ({}); - unit_type = Backend::named_type ("()", unit_type_node, BUILTINS_LOCATION); + unit_type = Backend::named_type ("()", unit_type_node, locus); } return unit_type; } @@ -147,7 +149,7 @@ TyTyResolveCompile::visit (const TyTy::PlaceholderType &type) void TyTyResolveCompile::visit (const TyTy::ClosureType &type) { - auto mappings = ctx->get_mappings (); + auto &mappings = ctx->get_mappings (); std::vector<Backend::typed_identifier> fields; @@ -155,9 +157,9 @@ TyTyResolveCompile::visit (const TyTy::ClosureType &type) for (const auto &capture : type.get_captures ()) { // lookup the HirId - HirId ref = UNKNOWN_HIRID; - bool ok = mappings->lookup_node_to_hir (capture, &ref); - rust_assert (ok); + tl::optional<HirId> hid = mappings.lookup_node_to_hir (capture); + rust_assert (hid.has_value ()); + auto ref = hid.value (); // lookup the var decl type TyTy::BaseType *lookup = nullptr; @@ -201,20 +203,20 @@ TyTyResolveCompile::visit (const TyTy::FnType &type) { auto ret = TyTyResolveCompile::compile (ctx, hir_type, trait_object_mode); location_t return_type_locus - = ctx->get_mappings ()->lookup_location (hir_type->get_ref ()); + = ctx->get_mappings ().lookup_location (hir_type->get_ref ()); results.push_back ( Backend::typed_identifier ("_", ret, return_type_locus)); } for (auto ¶m_pair : type.get_params ()) { - auto param_tyty = param_pair.second; + auto param_tyty = param_pair.get_type (); auto compiled_param_type = TyTyResolveCompile::compile (ctx, param_tyty, trait_object_mode); auto compiled_param = Backend::typed_identifier ( - param_pair.first->as_string (), compiled_param_type, - ctx->get_mappings ()->lookup_location (param_tyty->get_ref ())); + param_pair.get_pattern ().as_string (), compiled_param_type, + ctx->get_mappings ().lookup_location (param_tyty->get_ref ())); parameters.push_back (compiled_param); } @@ -263,13 +265,13 @@ TyTyResolveCompile::visit (const TyTy::ADTType &type) = TyTyResolveCompile::compile (ctx, field->get_field_type ()); Backend::typed_identifier f (field->get_name (), compiled_field_ty, - ctx->get_mappings ()->lookup_location ( + ctx->get_mappings ().lookup_location ( type.get_ty_ref ())); fields.push_back (std::move (f)); } - type_record = type.is_union () ? Backend::union_type (fields) - : Backend::struct_type (fields); + type_record = type.is_union () ? Backend::union_type (fields, false) + : Backend::struct_type (fields, false); } else { @@ -297,21 +299,39 @@ TyTyResolveCompile::visit (const TyTy::ADTType &type) // Ada, qual_union_types might still work for this but I am not 100% sure. // I ran into some issues lets reuse our normal union and ask Ada people // about it. + // + // I think the above is actually wrong and it should actually be this + // + // struct { + // int RUST$ENUM$DISR; // take into account the repr for this TODO + // union { + // // Variant A + // struct { + // // No additional fields + // } A; + + // // Variant B + // struct { + // // No additional fields + // } B; + + // // Variant C + // struct { + // char c; + // } C; + + // // Variant D + // struct { + // int64_t x; + // int64_t y; + // } D; + // } payload; // The union of all variant data + // }; std::vector<tree> variant_records; for (auto &variant : type.get_variants ()) { std::vector<Backend::typed_identifier> fields; - - // add in the qualifier field for the variant - tree enumeral_type - = TyTyResolveCompile::get_implicit_enumeral_node_type (ctx); - Backend::typed_identifier f (RUST_ENUM_DISR_FIELD_NAME, enumeral_type, - ctx->get_mappings ()->lookup_location ( - variant->get_id ())); - fields.push_back (std::move (f)); - - // compile the rest of the fields for (size_t i = 0; i < variant->num_fields (); i++) { const TyTy::StructFieldType *field @@ -326,7 +346,7 @@ TyTyResolveCompile::visit (const TyTy::ADTType &type) Backend::typed_identifier f ( field_name, compiled_field_ty, - ctx->get_mappings ()->lookup_location (type.get_ty_ref ())); + ctx->get_mappings ().lookup_location (type.get_ty_ref ())); fields.push_back (std::move (f)); } @@ -335,9 +355,6 @@ TyTyResolveCompile::visit (const TyTy::ADTType &type) = Backend::named_type (variant->get_ident ().path.get (), variant_record, variant->get_ident ().locus); - // set the qualifier to be a builtin - DECL_ARTIFICIAL (TYPE_FIELDS (variant_record)) = 1; - // add them to the list variant_records.push_back (named_variant_record); } @@ -353,13 +370,32 @@ TyTyResolveCompile::visit (const TyTy::ADTType &type) std::string implicit_variant_name = variant->get_identifier (); Backend::typed_identifier f (implicit_variant_name, variant_record, - ctx->get_mappings ()->lookup_location ( + ctx->get_mappings ().lookup_location ( type.get_ty_ref ())); enum_fields.push_back (std::move (f)); } + // + location_t locus = ctx->get_mappings ().lookup_location (type.get_ref ()); + // finally make the union or the enum - type_record = Backend::union_type (enum_fields); + tree variants_union = Backend::union_type (enum_fields, false); + layout_type (variants_union); + tree named_union_record + = Backend::named_type ("payload", variants_union, locus); + + // create the overall struct + tree enumeral_type = TyTyResolveCompile::get_implicit_enumeral_node_type ( + type.get_repr_options ().repr); + Backend::typed_identifier discrim (RUST_ENUM_DISR_FIELD_NAME, + enumeral_type, locus); + Backend::typed_identifier variants_union_field ("payload", + named_union_record, + locus); + + std::vector<Backend::typed_identifier> fields + = {discrim, variants_union_field}; + type_record = Backend::struct_type (fields, false); } // Handle repr options @@ -381,6 +417,7 @@ TyTyResolveCompile::visit (const TyTy::ADTType &type) SET_TYPE_ALIGN (type_record, repr.align * 8); TYPE_USER_ALIGN (type_record) = 1; } + layout_type (type_record); std::string named_struct_str = type.get_ident ().path.get () + type.subst_as_string (); @@ -411,13 +448,13 @@ TyTyResolveCompile::visit (const TyTy::TupleType &type) // approach makes it simpler to use a C-only debugger, or // GDB's C mode, when debugging Rust. Backend::typed_identifier f ("__" + std::to_string (i), compiled_field_ty, - ctx->get_mappings ()->lookup_location ( + ctx->get_mappings ().lookup_location ( type.get_ty_ref ())); fields.push_back (std::move (f)); } tree struct_type_record = Backend::struct_type (fields); - translated = Backend::named_type (type.as_string (), struct_type_record, + translated = Backend::named_type (type.get_name (), struct_type_record, type.get_ident ().locus); } @@ -428,12 +465,24 @@ TyTyResolveCompile::visit (const TyTy::ArrayType &type) = TyTyResolveCompile::compile (ctx, type.get_element_type ()); ctx->push_const_context (); - tree capacity_expr = CompileExpr::Compile (&type.get_capacity_expr (), ctx); + + HIR::Expr &hir_capacity_expr = type.get_capacity_expr (); + TyTy::BaseType *capacity_expr_ty = nullptr; + bool ok = ctx->get_tyctx ()->lookup_type ( + hir_capacity_expr.get_mappings ().get_hirid (), &capacity_expr_ty); + rust_assert (ok); + tree capacity_expr = HIRCompileBase::compile_constant_expr ( + ctx, hir_capacity_expr.get_mappings ().get_hirid (), capacity_expr_ty, + capacity_expr_ty, Resolver::CanonicalPath::create_empty (), + hir_capacity_expr, type.get_locus (), hir_capacity_expr.get_locus ()); + ctx->pop_const_context (); tree folded_capacity_expr = fold_expr (capacity_expr); translated = Backend::array_type (element_type, folded_capacity_expr); + if (translated != error_mark_node) + translated = ctx->insert_compiled_type (translated); } void @@ -703,6 +752,14 @@ TyTyResolveCompile::visit (const TyTy::DynamicObjectType &type) type.get_ident ().locus); } +void +TyTyResolveCompile::visit (const TyTy::OpaqueType &type) +{ + rust_assert (type.can_resolve ()); + auto underlying = type.resolve (); + translated = TyTyResolveCompile::compile (ctx, underlying, trait_object_mode); +} + tree TyTyResolveCompile::create_dyn_obj_record (const TyTy::DynamicObjectType &type) { @@ -714,14 +771,14 @@ TyTyResolveCompile::create_dyn_obj_record (const TyTy::DynamicObjectType &type) tree uintptr_ty = build_pointer_type (uint); Backend::typed_identifier f ("pointer", uintptr_ty, - ctx->get_mappings ()->lookup_location ( + ctx->get_mappings ().lookup_location ( type.get_ty_ref ())); fields.push_back (std::move (f)); tree vtable_size = build_int_cst (size_type_node, items.size ()); tree vtable_type = Backend::array_type (uintptr_ty, vtable_size); Backend::typed_identifier vtf ("vtable", vtable_type, - ctx->get_mappings ()->lookup_location ( + ctx->get_mappings ().lookup_location ( type.get_ty_ref ())); fields.push_back (std::move (vtf)); diff --git a/gcc/rust/backend/rust-compile-type.h b/gcc/rust/backend/rust-compile-type.h index 44bd218..aa20067 100644 --- a/gcc/rust/backend/rust-compile-type.h +++ b/gcc/rust/backend/rust-compile-type.h @@ -30,8 +30,6 @@ public: static tree compile (Context *ctx, const TyTy::BaseType *ty, bool trait_object_mode = false); - static tree get_implicit_enumeral_node_type (Context *ctx); - static tree get_unit_type (Context *ctx); void visit (const TyTy::InferType &) override; @@ -58,6 +56,7 @@ public: void visit (const TyTy::ProjectionType &) override; void visit (const TyTy::DynamicObjectType &) override; void visit (const TyTy::ClosureType &) override; + void visit (const TyTy::OpaqueType &) override; public: static hashval_t type_hasher (tree type); @@ -66,6 +65,7 @@ protected: tree create_slice_type_record (const TyTy::SliceType &type); tree create_str_type_record (const TyTy::StrType &type); tree create_dyn_obj_record (const TyTy::DynamicObjectType &type); + tree get_implicit_enumeral_node_type (TyTy::BaseType *repr); private: TyTyResolveCompile (Context *ctx, bool trait_object_mode); diff --git a/gcc/rust/backend/rust-compile-var-decl.h b/gcc/rust/backend/rust-compile-var-decl.h index 45ca01d..eda2335 100644 --- a/gcc/rust/backend/rust-compile-var-decl.h +++ b/gcc/rust/backend/rust-compile-var-decl.h @@ -68,12 +68,12 @@ public: void visit (HIR::TuplePattern &pattern) override { - switch (pattern.get_items ()->get_item_type ()) + switch (pattern.get_items ().get_item_type ()) { case HIR::TuplePatternItems::ItemType::MULTIPLE: { rust_assert (TREE_CODE (translated_type) == RECORD_TYPE); auto &items = static_cast<HIR::TuplePatternItemsMultiple &> ( - *pattern.get_items ()); + pattern.get_items ()); size_t offs = 0; for (auto &sub : items.get_patterns ()) diff --git a/gcc/rust/backend/rust-compile.cc b/gcc/rust/backend/rust-compile.cc index 5b07d79..2d197ed 100644 --- a/gcc/rust/backend/rust-compile.cc +++ b/gcc/rust/backend/rust-compile.cc @@ -189,7 +189,7 @@ HIRCompileBase::coerce_to_dyn_object (tree compiled_ref, location_t locus) { // DST's get wrapped in a pseudo reference that doesnt exist... - const TyTy::ReferenceType r (ctx->get_mappings ()->get_next_hir_id (), + const TyTy::ReferenceType r (ctx->get_mappings ().get_next_hir_id (), TyTy::TyVar (ty->get_ref ()), Mutability::Imm); tree dynamic_object = TyTyResolveCompile::compile (ctx, &r); @@ -241,100 +241,84 @@ HIRCompileBase::compute_address_for_trait_item ( &receiver_bounds, const TyTy::BaseType *receiver, const TyTy::BaseType *root, location_t locus) { - // There are two cases here one where its an item which has an implementation - // within a trait-impl-block. Then there is the case where there is a default - // implementation for this within the trait. - // - // The awkward part here is that this might be a generic trait and we need to - // figure out the correct monomorphized type for this so we can resolve the - // address of the function , this is stored as part of the - // type-bound-predicate - // - // Algo: - // check if there is an impl-item for this trait-item-ref first - // else assert that the trait-item-ref has an implementation - // - // FIXME this does not support super traits - TyTy::TypeBoundPredicateItem predicate_item = predicate->lookup_associated_item (ref->get_identifier ()); rust_assert (!predicate_item.is_error ()); - // this is the expected end type + // This is the expected end type TyTy::BaseType *trait_item_type = predicate_item.get_tyty_for_receiver (root); rust_assert (trait_item_type->get_kind () == TyTy::TypeKind::FNDEF); TyTy::FnType *trait_item_fntype = static_cast<TyTy::FnType *> (trait_item_type); - // find impl-block for this trait-item-ref - HIR::ImplBlock *associated_impl_block = nullptr; - const Resolver::TraitReference *predicate_trait_ref = predicate->get (); + // Loop through the list of trait references and impls that we satisfy. + // We are looking for one that has an implementation for "ref", a trait + // item. for (auto &item : receiver_bounds) { - Resolver::TraitReference *trait_ref = item.first; HIR::ImplBlock *impl_block = item.second; - if (predicate_trait_ref->is_equal (*trait_ref)) + rust_assert (impl_block != nullptr); + + // Checks for empty impl blocks, triggered by Sized trait. + if (!impl_block->has_type ()) + continue; + + // Lookup type for potentially associated impl. + HIR::Type &self_type_path = impl_block->get_type (); + + // Convert HIR::Type to TyTy::BaseType + TyTy::BaseType *self = nullptr; + bool ok = ctx->get_tyctx ()->lookup_type ( + self_type_path.get_mappings ().get_hirid (), &self); + + rust_assert (ok); + + // Look through the relevant bounds on our type, and find which one our + // impl block satisfies + TyTy::TypeBoundPredicate *self_bound = nullptr; + for (auto &bound : self->get_specified_bounds ()) { - associated_impl_block = impl_block; - break; + const Resolver::TraitReference *bound_ref = bound.get (); + const Resolver::TraitReference *specified_ref = predicate->get (); + // If this impl is for one of our types or supertypes + if (specified_ref->satisfies_bound (*bound_ref)) + { + self_bound = &bound; + break; + } } - } - // FIXME this probably should just return error_mark_node but this helps - // debug for now since we are wrongly returning early on type-resolution - // failures, until we take advantage of more error types and error_mark_node - rust_assert (associated_impl_block != nullptr); - - // lookup self for the associated impl - std::unique_ptr<HIR::Type> &self_type_path - = associated_impl_block->get_type (); - TyTy::BaseType *self = nullptr; - bool ok = ctx->get_tyctx ()->lookup_type ( - self_type_path->get_mappings ().get_hirid (), &self); - rust_assert (ok); - - // lookup the predicate item from the self - TyTy::TypeBoundPredicate *self_bound = nullptr; - for (auto &bound : self->get_specified_bounds ()) - { - const Resolver::TraitReference *bound_ref = bound.get (); - const Resolver::TraitReference *specified_ref = predicate->get (); - if (bound_ref->is_equal (*specified_ref)) + // This impl block doesn't help us + if (self_bound == nullptr) + continue; + + // Find the specific function in the impl block that matches "ref". + // This is the one we want to compute the address for. + HIR::Function *associated_function = nullptr; + for (auto &impl_item : impl_block->get_impl_items ()) { - self_bound = &bound; - break; + bool is_function = impl_item->get_impl_item_type () + == HIR::ImplItem::ImplItemType::FUNCTION; + if (!is_function) + continue; + + HIR::Function *fn = static_cast<HIR::Function *> (impl_item.get ()); + bool found_associated_item + = fn->get_function_name ().as_string ().compare ( + ref->get_identifier ()) + == 0; + if (found_associated_item) + associated_function = fn; } - } - rust_assert (self_bound != nullptr); - - // lookup the associated item from the associated impl block - TyTy::TypeBoundPredicateItem associated_self_item - = self_bound->lookup_associated_item (ref->get_identifier ()); - rust_assert (!associated_self_item.is_error ()); - // Lookup the impl-block for the associated impl_item if it exists - HIR::Function *associated_function = nullptr; - for (auto &impl_item : associated_impl_block->get_impl_items ()) - { - bool is_function = impl_item->get_impl_item_type () - == HIR::ImplItem::ImplItemType::FUNCTION; - if (!is_function) + // This impl block satisfies the bound, but doesn't contain the relevant + // function. This could happen because of supertraits. + if (associated_function == nullptr) continue; - HIR::Function *fn = static_cast<HIR::Function *> (impl_item.get ()); - bool found_associated_item - = fn->get_function_name ().as_string ().compare (ref->get_identifier ()) - == 0; - if (found_associated_item) - associated_function = fn; - } - - // we found an impl_item for this - if (associated_function != nullptr) - { // lookup the associated type for this item TyTy::BaseType *lookup = nullptr; - bool ok = ctx->get_tyctx ()->lookup_type ( + ok = ctx->get_tyctx ()->lookup_type ( associated_function->get_mappings ().get_hirid (), &lookup); rust_assert (ok); rust_assert (lookup->get_kind () == TyTy::TypeKind::FNDEF); @@ -354,7 +338,7 @@ HIRCompileBase::compute_address_for_trait_item ( } return CompileInherentImplItem::Compile (associated_function, ctx, - lookup_fntype, true, locus); + lookup_fntype, locus); } // we can only compile trait-items with a body diff --git a/gcc/rust/backend/rust-constexpr.cc b/gcc/rust/backend/rust-constexpr.cc index bfd7d95..0ed56c7 100644 --- a/gcc/rust/backend/rust-constexpr.cc +++ b/gcc/rust/backend/rust-constexpr.cc @@ -1901,6 +1901,9 @@ eval_constant_expression (const constexpr_ctx *ctx, tree t, bool lval, location_t loc = EXPR_LOCATION (t); + if (t == NULL_TREE) + return NULL_TREE; + if (CONSTANT_CLASS_P (t)) { if (TREE_OVERFLOW (t)) @@ -2697,10 +2700,8 @@ eval_store_expression (const constexpr_ctx *ctx, tree t, bool lval, } if (TREE_CODE (probe) == ARRAY_REF) { - // TODO - rust_unreachable (); - // elt = eval_and_check_array_index (ctx, probe, false, - // non_constant_p, overflow_p); + elt = eval_and_check_array_index (ctx, probe, false, + non_constant_p, overflow_p); if (*non_constant_p) return t; } @@ -2929,8 +2930,13 @@ eval_store_expression (const constexpr_ctx *ctx, tree t, bool lval, } } + if (*non_constant_p) + return t; + /* Don't share a CONSTRUCTOR that might be changed later. */ init = unshare_constructor (init); + if (init == NULL_TREE) + return t; if (*valp && TREE_CODE (*valp) == CONSTRUCTOR && TREE_CODE (init) == CONSTRUCTOR) @@ -3585,9 +3591,6 @@ eval_call_expression (const constexpr_ctx *ctx, tree t, bool lval, result = *ctx->global->values.get (res); if (result == NULL_TREE && !*non_constant_p) { - if (!ctx->quiet) - error ("%<constexpr%> call flows off the end " - "of the function"); *non_constant_p = true; } } diff --git a/gcc/rust/backend/rust-mangle-legacy.cc b/gcc/rust/backend/rust-mangle-legacy.cc index 2826b36..3533e12 100644 --- a/gcc/rust/backend/rust-mangle-legacy.cc +++ b/gcc/rust/backend/rust-mangle-legacy.cc @@ -21,7 +21,6 @@ #include "rust-unicode.h" #include "rust-diagnostics.h" #include "rust-system.h" -#include <sstream> namespace Rust { namespace Compile { diff --git a/gcc/rust/backend/rust-mangle-v0.cc b/gcc/rust/backend/rust-mangle-v0.cc index 3e25ac3..1bff44b 100644 --- a/gcc/rust/backend/rust-mangle-v0.cc +++ b/gcc/rust/backend/rust-mangle-v0.cc @@ -25,7 +25,6 @@ #include "rust-unicode.h" #include "rust-punycode.h" #include "rust-compile-type.h" -#include <sstream> namespace Rust { namespace Compile { @@ -279,16 +278,17 @@ v0_type_path (V0Path path, std::string ident) } static V0Path -v0_function_path (V0Path path, Rust::Compile::Context *ctx, - const TyTy::BaseType *ty, HIR::Function *fn, - std::string ident) +v0_function_path ( + V0Path path, Rust::Compile::Context *ctx, const TyTy::BaseType *ty, + const std::vector<std::unique_ptr<HIR::GenericParam>> &generic_params, + std::string ident) { V0Path v0path; v0path.prefix = "N"; v0path.ns = "v"; v0path.path = path.as_string (); v0path.ident = ident; - if (!fn->get_generic_params ().empty ()) + if (!generic_params.empty ()) { v0path.generic_prefix = "I"; v0path.generic_postfix = v0_generic_args (ctx, ty) + "E"; @@ -327,7 +327,7 @@ v0_inherent_or_trait_impl_path (Rust::Compile::Context *ctx, // lookup impl type TyTy::BaseType *impl_ty = nullptr; ok = ctx->get_tyctx ()->lookup_type ( - impl_block->get_type ()->get_mappings ().get_hirid (), &impl_ty); + impl_block->get_type ().get_mappings ().get_hirid (), &impl_ty); rust_assert (ok); // FIXME: dummy value for now @@ -341,7 +341,7 @@ v0_inherent_or_trait_impl_path (Rust::Compile::Context *ctx, TyTy::BaseType *trait_ty = nullptr; ok = ctx->get_tyctx ()->lookup_type ( - impl_block->get_trait_ref ()->get_mappings ().get_hirid (), &trait_ty); + impl_block->get_trait_ref ().get_mappings ().get_hirid (), &trait_ty); rust_assert (ok); v0path.trait_type = v0_type_prefix (ctx, trait_ty); @@ -369,34 +369,30 @@ static std::string v0_path (Rust::Compile::Context *ctx, const TyTy::BaseType *ty, const Resolver::CanonicalPath &cpath) { - auto mappings = Analysis::Mappings::get (); + auto &mappings = Analysis::Mappings::get (); V0Path v0path = {}; cpath.iterate_segs ([&] (const Resolver::CanonicalPath &seg) { - HirId hir_id; - bool ok = mappings->lookup_node_to_hir (seg.get_node_id (), &hir_id); - if (!ok) + tl::optional<HirId> hid = mappings.lookup_node_to_hir (seg.get_node_id ()); + if (!hid.has_value ()) { // FIXME: generic arg in canonical path? (e.g. <i32> in crate::S<i32>) rust_unreachable (); } - HirId parent_impl_id = UNKNOWN_HIRID; - HIR::ImplItem *impl_item - = mappings->lookup_hir_implitem (hir_id, &parent_impl_id); - HIR::TraitItem *trait_item = mappings->lookup_hir_trait_item (hir_id); - HIR::Item *item = mappings->lookup_hir_item (hir_id); - HIR::Expr *expr = mappings->lookup_hir_expr (hir_id); + auto hir_id = hid.value (); - if (impl_item != nullptr) + if (auto impl_item = mappings.lookup_hir_implitem (hir_id)) { - switch (impl_item->get_impl_item_type ()) + switch (impl_item->first->get_impl_item_type ()) { case HIR::ImplItem::FUNCTION: { - HIR::Function *fn = static_cast<HIR::Function *> (impl_item); - v0path = v0_function_path (v0path, ctx, ty, fn, - v0_identifier (seg.get ())); + HIR::Function *fn + = static_cast<HIR::Function *> (impl_item->first); + v0path + = v0_function_path (v0path, ctx, ty, fn->get_generic_params (), + v0_identifier (seg.get ())); } break; case HIR::ImplItem::CONSTANT: @@ -408,13 +404,15 @@ v0_path (Rust::Compile::Context *ctx, const TyTy::BaseType *ty, break; } } - else if (trait_item != nullptr) + else if (auto trait_item = mappings.lookup_hir_trait_item (hir_id)) { - switch (trait_item->get_item_kind ()) + switch (trait_item.value ()->get_item_kind ()) { case HIR::TraitItem::FUNC: { - HIR::Function *fn = static_cast<HIR::Function *> (impl_item); - v0path = v0_function_path (v0path, ctx, ty, fn, + auto fn = static_cast<HIR::TraitItemFunc *> (*trait_item); + rust_unreachable (); + v0path = v0_function_path (v0path, ctx, ty, + fn->get_decl ().get_generic_params (), v0_identifier (seg.get ())); } break; @@ -427,13 +425,14 @@ v0_path (Rust::Compile::Context *ctx, const TyTy::BaseType *ty, break; } } - else if (item != nullptr) - switch (item->get_item_kind ()) + else if (auto item = mappings.lookup_hir_item (hir_id)) + switch (item.value ()->get_item_kind ()) { case HIR::Item::ItemKind::Function: { - HIR::Function *fn = static_cast<HIR::Function *> (item); - v0path = v0_function_path (v0path, ctx, ty, fn, - v0_identifier (seg.get ())); + HIR::Function *fn = static_cast<HIR::Function *> (*item); + v0path + = v0_function_path (v0path, ctx, ty, fn->get_generic_params (), + v0_identifier (seg.get ())); } break; case HIR::Item::ItemKind::Module: @@ -452,7 +451,7 @@ v0_path (Rust::Compile::Context *ctx, const TyTy::BaseType *ty, case HIR::Item::ItemKind::Impl: // Trait impl or inherent impl. { - HIR::ImplBlock *impl_block = static_cast<HIR::ImplBlock *> (item); + HIR::ImplBlock *impl_block = static_cast<HIR::ImplBlock *> (*item); v0path = v0_inherent_or_trait_impl_path (ctx, impl_block); } break; @@ -465,9 +464,9 @@ v0_path (Rust::Compile::Context *ctx, const TyTy::BaseType *ty, cpath.get ().c_str ()); break; } - else if (expr != nullptr) + else if (auto expr = mappings.lookup_hir_expr (hir_id)) { - rust_assert (expr->get_expression_type () + rust_assert (expr.value ()->get_expression_type () == HIR::Expr::ExprType::Closure); // Use HIR ID as disambiguator. v0path = v0_closure (v0path, hir_id); @@ -490,7 +489,7 @@ v0_mangle_item (Rust::Compile::Context *ctx, const TyTy::BaseType *ty, rust_debug ("Start mangling: %s", path.get ().c_str ()); // TODO: get Instanciating CrateNum - // auto mappings = Analysis::Mappings::get (); + // auto &mappings = Analysis::Mappings::get (); // std::string crate_name; // bool ok = mappings->get_crate_name (path.get_crate_num (), crate_name); // rust_assert (ok); |