public inbox for gcc-cvs@sourceware.org
help / color / mirror / Atom feed
* [gcc/devel/rust/master] Support extern-blocks defined within blocks
@ 2022-06-08 12:47 Thomas Schwinge
  0 siblings, 0 replies; only message in thread
From: Thomas Schwinge @ 2022-06-08 12:47 UTC (permalink / raw)
  To: gcc-cvs

https://gcc.gnu.org/g:4a4206c017654af7a3468690e4e21fdaf86bcb5c

commit 4a4206c017654af7a3468690e4e21fdaf86bcb5c
Author: Philip Herron <philip.herron@embecosm.com>
Date:   Mon May 16 17:09:45 2022 +0100

    Support extern-blocks defined within blocks
    
    This adds support for declaring extern blocks within blocks. So this adds
    the missing name resolution visitor for the statement context. Then we
    extract out a common extern block hir lowering function for both contexts.
    
    The type resolution step needs to be updated to be like the code-generation
    step so that we can solve these paths in a query rather than a top down
    approach but this is a known issue.
    
    The final step was to support query based compilation to extern functions.
    
    Fixes #976

Diff:
---
 gcc/rust/Make-lang.in                           |  1 +
 gcc/rust/backend/rust-compile-base.cc           |  8 ++-
 gcc/rust/backend/rust-compile-extern.h          | 27 ++++++++--
 gcc/rust/backend/rust-compile-resolve-path.cc   | 16 +++++-
 gcc/rust/hir/rust-ast-lower-base.cc             | 68 +++++++++++++++++++++----
 gcc/rust/hir/rust-ast-lower-base.h              |  2 +
 gcc/rust/hir/rust-ast-lower-item.cc             | 41 +--------------
 gcc/rust/hir/rust-ast-lower-stmt.h              |  5 ++
 gcc/rust/resolve/rust-ast-resolve-stmt.cc       | 38 ++++++++++++++
 gcc/rust/resolve/rust-ast-resolve-stmt.h        |  2 +
 gcc/rust/typecheck/rust-hir-type-check-stmt.h   |  9 ++++
 gcc/rust/typecheck/rust-hir-type-check.cc       |  7 +--
 gcc/testsuite/rust/execute/torture/issue-976.rs | 14 +++++
 13 files changed, 172 insertions(+), 66 deletions(-)

diff --git a/gcc/rust/Make-lang.in b/gcc/rust/Make-lang.in
index 738cfdf20ef..2d701ea25ee 100644
--- a/gcc/rust/Make-lang.in
+++ b/gcc/rust/Make-lang.in
@@ -94,6 +94,7 @@ GRS_OBJS = \
     rust/rust-ast-resolve-expr.o \
     rust/rust-ast-resolve-type.o \
     rust/rust-ast-resolve-path.o \
+    rust/rust-ast-resolve-stmt.o \
     rust/rust-hir-type-check.o \
     rust/rust-privacy-check.o \
     rust/rust-privacy-ctx.o \
diff --git a/gcc/rust/backend/rust-compile-base.cc b/gcc/rust/backend/rust-compile-base.cc
index 6773ac61382..7b0a375439c 100644
--- a/gcc/rust/backend/rust-compile-base.cc
+++ b/gcc/rust/backend/rust-compile-base.cc
@@ -343,8 +343,12 @@ HIRCompileBase::compile_locals_for_block (Context *ctx, Resolver::Rib &rib,
       rust_assert (ok);
 
       HIR::Stmt *decl = nullptr;
-      ok = ctx->get_mappings ()->resolve_nodeid_to_stmt (d.parent, &decl);
-      rust_assert (ok);
+      if (!ctx->get_mappings ()->resolve_nodeid_to_stmt (d.parent, &decl))
+	{
+	  // might be an extern block see fix for
+	  // https://github.com/Rust-GCC/gccrs/issues/976
+	  continue;
+	}
 
       // if its a function we extract this out side of this fn context
       // and it is not a local to this function
diff --git a/gcc/rust/backend/rust-compile-extern.h b/gcc/rust/backend/rust-compile-extern.h
index 1987805146d..c24437deb2f 100644
--- a/gcc/rust/backend/rust-compile-extern.h
+++ b/gcc/rust/backend/rust-compile-extern.h
@@ -29,11 +29,19 @@ class CompileExternItem : public HIRCompileBase,
 			  public HIR::HIRExternalItemVisitor
 {
 public:
-  static void compile (HIR::ExternalItem *item, Context *ctx,
-		       TyTy::BaseType *concrete = nullptr)
+  static tree compile (HIR::ExternalItem *item, Context *ctx,
+		       TyTy::BaseType *concrete = nullptr,
+		       bool is_query_mode = false,
+		       Location ref_locus = Location ())
   {
-    CompileExternItem compiler (ctx, concrete);
+    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;
   }
 
   void visit (HIR::ExternalStaticItem &item) override
@@ -58,6 +66,8 @@ public:
 					      item.get_locus ());
     ctx->insert_var_decl (item.get_mappings ().get_hirid (), static_global);
     ctx->push_var (static_global);
+
+    reference = ctx->get_backend ()->var_expression (static_global, ref_locus);
   }
 
   void visit (HIR::ExternalFunctionItem &function) override
@@ -129,14 +139,21 @@ public:
     setup_abi_options (fndecl, fntype->get_abi ());
 
     ctx->insert_function_decl (fntype, fndecl);
+
+    reference
+      = address_expression (fndecl, build_pointer_type (TREE_TYPE (fndecl)),
+			    ref_locus);
   }
 
 private:
-  CompileExternItem (Context *ctx, TyTy::BaseType *concrete)
-    : HIRCompileBase (ctx), concrete (concrete)
+  CompileExternItem (Context *ctx, TyTy::BaseType *concrete, Location ref_locus)
+    : HIRCompileBase (ctx), concrete (concrete), reference (error_mark_node),
+      ref_locus (ref_locus)
   {}
 
   TyTy::BaseType *concrete;
+  tree reference;
+  Location ref_locus;
 };
 
 } // namespace Compile
diff --git a/gcc/rust/backend/rust-compile-resolve-path.cc b/gcc/rust/backend/rust-compile-resolve-path.cc
index bd44bf45791..ca96a277ea8 100644
--- a/gcc/rust/backend/rust-compile-resolve-path.cc
+++ b/gcc/rust/backend/rust-compile-resolve-path.cc
@@ -23,8 +23,7 @@
 #include "rust-compile-expr.h"
 #include "rust-hir-trait-resolve.h"
 #include "rust-hir-path-probe.h"
-
-#include "print-tree.h"
+#include "rust-compile-extern.h"
 
 namespace Rust {
 namespace Compile {
@@ -172,7 +171,11 @@ HIRCompileBase::query_compile (HirId ref, TyTy::BaseType *lookup,
 {
   HIR::Item *resolved_item
     = ctx->get_mappings ()->lookup_hir_item (mappings.get_crate_num (), ref);
+  HIR::ExternalItem *resolved_extern_item
+    = ctx->get_mappings ()->lookup_hir_extern_item (mappings.get_crate_num (),
+						    ref);
   bool is_hir_item = resolved_item != nullptr;
+  bool is_hir_extern_item = resolved_extern_item != nullptr;
   if (is_hir_item)
     {
       if (!lookup->has_subsititions_defined ())
@@ -182,6 +185,15 @@ HIRCompileBase::query_compile (HirId ref, TyTy::BaseType *lookup,
 	return CompileItem::compile (resolved_item, ctx, lookup, true,
 				     expr_locus);
     }
+  else if (is_hir_extern_item)
+    {
+      if (!lookup->has_subsititions_defined ())
+	return CompileExternItem::compile (resolved_extern_item, ctx, nullptr,
+					   true, expr_locus);
+      else
+	return CompileExternItem::compile (resolved_extern_item, ctx, lookup,
+					   true, expr_locus);
+    }
   else
     {
       HirId parent_impl_id = UNKNOWN_HIRID;
diff --git a/gcc/rust/hir/rust-ast-lower-base.cc b/gcc/rust/hir/rust-ast-lower-base.cc
index 7afe75cd0ca..a4821329148 100644
--- a/gcc/rust/hir/rust-ast-lower-base.cc
+++ b/gcc/rust/hir/rust-ast-lower-base.cc
@@ -19,6 +19,7 @@
 #include "rust-ast-lower-base.h"
 #include "rust-ast-lower-type.h"
 #include "rust-ast-lower-pattern.h"
+#include "rust-ast-lower-extern.h"
 
 namespace Rust {
 namespace HIR {
@@ -545,11 +546,11 @@ ASTLoweringBase::lower_loop_label (AST::LoopLabel &loop_label)
   return HIR::LoopLabel (mapping, std::move (life), loop_label.get_locus ());
 }
 
-std::vector<std::unique_ptr<HIR::GenericParam> >
+std::vector<std::unique_ptr<HIR::GenericParam>>
 ASTLoweringBase::lower_generic_params (
-  std::vector<std::unique_ptr<AST::GenericParam> > &params)
+  std::vector<std::unique_ptr<AST::GenericParam>> &params)
 {
-  std::vector<std::unique_ptr<HIR::GenericParam> > lowered;
+  std::vector<std::unique_ptr<HIR::GenericParam>> lowered;
   for (auto &ast_param : params)
     {
       auto hir_param = ASTLowerGenericParam::translate (ast_param.get ());
@@ -601,7 +602,7 @@ ASTLoweringBase::lower_generic_args (AST::GenericArgs &args)
       lifetime_args.push_back (std::move (l));
     }
 
-  std::vector<std::unique_ptr<HIR::Type> > type_args;
+  std::vector<std::unique_ptr<HIR::Type>> type_args;
   for (auto &type : args.get_type_args ())
     {
       HIR::Type *t = ASTLoweringType::translate (type.get ());
@@ -653,7 +654,7 @@ ASTLowerTypePath::visit (AST::TypePathSegmentGeneric &segment)
       lifetime_args.push_back (std::move (l));
     }
 
-  std::vector<std::unique_ptr<HIR::Type> > type_args;
+  std::vector<std::unique_ptr<HIR::Type>> type_args;
   for (auto &type : segment.get_generic_args ().get_type_args ())
     {
       HIR::Type *t = ASTLoweringType::translate (type.get ());
@@ -700,7 +701,7 @@ ASTLowerQualifiedPathInType::visit (AST::QualifiedPathInType &path)
     }
   std::unique_ptr<HIR::TypePathSegment> associated_segment (translated_segment);
 
-  std::vector<std::unique_ptr<HIR::TypePathSegment> > translated_segments;
+  std::vector<std::unique_ptr<HIR::TypePathSegment>> translated_segments;
   for (auto &seg : path.get_segments ())
     {
       translated_segment = nullptr;
@@ -728,7 +729,7 @@ ASTLowerQualifiedPathInType::visit (AST::QualifiedPathInType &path)
 void
 ASTLoweringType::visit (AST::TraitObjectTypeOneBound &type)
 {
-  std::vector<std::unique_ptr<HIR::TypeParamBound> > bounds;
+  std::vector<std::unique_ptr<HIR::TypeParamBound>> bounds;
   HIR::TypeParamBound *translated_bound
     = ASTLoweringTypeBounds::translate (&type.get_trait_bound ());
   bounds.push_back (std::unique_ptr<HIR::TypeParamBound> (translated_bound));
@@ -748,7 +749,7 @@ ASTLoweringType::visit (AST::TraitObjectTypeOneBound &type)
 void
 ASTLoweringType::visit (AST::TraitObjectType &type)
 {
-  std::vector<std::unique_ptr<HIR::TypeParamBound> > bounds;
+  std::vector<std::unique_ptr<HIR::TypeParamBound>> bounds;
 
   for (auto &bound : type.get_type_param_bounds ())
     {
@@ -915,7 +916,7 @@ std::unique_ptr<HIR::TuplePatternItems>
 ASTLoweringBase::lower_tuple_pattern_multiple (
   AST::TuplePatternItemsMultiple &pattern)
 {
-  std::vector<std::unique_ptr<HIR::Pattern> > patterns;
+  std::vector<std::unique_ptr<HIR::Pattern>> patterns;
   for (auto &p : pattern.get_patterns ())
     {
       HIR::Pattern *translated = ASTLoweringPattern::translate (p.get ());
@@ -930,8 +931,8 @@ std::unique_ptr<TuplePatternItems>
 ASTLoweringBase::lower_tuple_pattern_ranged (
   AST::TuplePatternItemsRanged &pattern)
 {
-  std::vector<std::unique_ptr<HIR::Pattern> > lower_patterns;
-  std::vector<std::unique_ptr<HIR::Pattern> > upper_patterns;
+  std::vector<std::unique_ptr<HIR::Pattern>> lower_patterns;
+  std::vector<std::unique_ptr<HIR::Pattern>> upper_patterns;
 
   for (auto &p : pattern.get_lower_patterns ())
     {
@@ -1030,5 +1031,50 @@ ASTLoweringBase::lower_literal (const AST::Literal &literal)
   return HIR::Literal (literal.as_string (), type, literal.get_type_hint ());
 }
 
+HIR::ExternBlock *
+ASTLoweringBase::lower_extern_block (AST::ExternBlock &extern_block)
+{
+  HIR::Visibility vis = translate_visibility (extern_block.get_visibility ());
+
+  std::vector<std::unique_ptr<HIR::ExternalItem>> extern_items;
+  for (auto &item : extern_block.get_extern_items ())
+    {
+      if (item->is_marked_for_strip ())
+	continue;
+
+      HIR::ExternalItem *lowered
+	= ASTLoweringExternItem::translate (item.get ());
+      extern_items.push_back (std::unique_ptr<HIR::ExternalItem> (lowered));
+    }
+
+  ABI abi = ABI::RUST;
+  if (extern_block.has_abi ())
+    {
+      const std::string &extern_abi = extern_block.get_abi ();
+      abi = get_abi_from_string (extern_abi);
+      if (abi == ABI::UNKNOWN)
+	rust_error_at (extern_block.get_locus (), "unknown ABI option");
+    }
+
+  auto crate_num = mappings->get_current_crate ();
+  Analysis::NodeMapping mapping (crate_num, extern_block.get_node_id (),
+				 mappings->get_next_hir_id (crate_num),
+				 mappings->get_next_localdef_id (crate_num));
+
+  HIR::ExternBlock *hir_extern_block
+    = new HIR::ExternBlock (mapping, abi, std::move (extern_items),
+			    std::move (vis), extern_block.get_inner_attrs (),
+			    extern_block.get_outer_attrs (),
+			    extern_block.get_locus ());
+
+  mappings->insert_defid_mapping (mapping.get_defid (), hir_extern_block);
+  mappings->insert_hir_item (mapping.get_crate_num (), mapping.get_hirid (),
+			     hir_extern_block);
+  mappings->insert_location (crate_num, mapping.get_hirid (),
+			     extern_block.get_locus ());
+
+  return hir_extern_block;
+}
+
 } // namespace HIR
 } // namespace Rust
diff --git a/gcc/rust/hir/rust-ast-lower-base.h b/gcc/rust/hir/rust-ast-lower-base.h
index 7e3eee134a1..aedec50109e 100644
--- a/gcc/rust/hir/rust-ast-lower-base.h
+++ b/gcc/rust/hir/rust-ast-lower-base.h
@@ -286,6 +286,8 @@ protected:
   lower_range_pattern_bound (AST::RangePatternBound *bound);
 
   HIR::Literal lower_literal (const AST::Literal &literal);
+
+  HIR::ExternBlock *lower_extern_block (AST::ExternBlock &extern_block);
 };
 
 } // namespace HIR
diff --git a/gcc/rust/hir/rust-ast-lower-item.cc b/gcc/rust/hir/rust-ast-lower-item.cc
index 588333817ef..5ab4dae5dab 100644
--- a/gcc/rust/hir/rust-ast-lower-item.cc
+++ b/gcc/rust/hir/rust-ast-lower-item.cc
@@ -752,46 +752,7 @@ ASTLoweringItem::visit (AST::TraitImpl &impl_block)
 void
 ASTLoweringItem::visit (AST::ExternBlock &extern_block)
 {
-  HIR::Visibility vis = translate_visibility (extern_block.get_visibility ());
-
-  std::vector<std::unique_ptr<HIR::ExternalItem>> extern_items;
-  for (auto &item : extern_block.get_extern_items ())
-    {
-      if (item->is_marked_for_strip ())
-	continue;
-
-      HIR::ExternalItem *lowered
-	= ASTLoweringExternItem::translate (item.get ());
-      extern_items.push_back (std::unique_ptr<HIR::ExternalItem> (lowered));
-    }
-
-  ABI abi = ABI::RUST;
-  if (extern_block.has_abi ())
-    {
-      const std::string &extern_abi = extern_block.get_abi ();
-      abi = get_abi_from_string (extern_abi);
-      if (abi == ABI::UNKNOWN)
-	rust_error_at (extern_block.get_locus (), "unknown ABI option");
-    }
-
-  auto crate_num = mappings->get_current_crate ();
-  Analysis::NodeMapping mapping (crate_num, extern_block.get_node_id (),
-				 mappings->get_next_hir_id (crate_num),
-				 mappings->get_next_localdef_id (crate_num));
-
-  HIR::ExternBlock *hir_extern_block
-    = new HIR::ExternBlock (mapping, abi, std::move (extern_items),
-			    std::move (vis), extern_block.get_inner_attrs (),
-			    extern_block.get_outer_attrs (),
-			    extern_block.get_locus ());
-
-  translated = hir_extern_block;
-
-  mappings->insert_defid_mapping (mapping.get_defid (), translated);
-  mappings->insert_hir_item (mapping.get_crate_num (), mapping.get_hirid (),
-			     translated);
-  mappings->insert_location (crate_num, mapping.get_hirid (),
-			     extern_block.get_locus ());
+  translated = lower_extern_block (extern_block);
 }
 
 HIR::SimplePath
diff --git a/gcc/rust/hir/rust-ast-lower-stmt.h b/gcc/rust/hir/rust-ast-lower-stmt.h
index 3ce77b4d9ca..199d146f5d5 100644
--- a/gcc/rust/hir/rust-ast-lower-stmt.h
+++ b/gcc/rust/hir/rust-ast-lower-stmt.h
@@ -437,6 +437,11 @@ public:
     translated = fn;
   }
 
+  void visit (AST::ExternBlock &extern_block) override
+  {
+    translated = lower_extern_block (extern_block);
+  }
+
 private:
   ASTLoweringStmt () : translated (nullptr), terminated (false) {}
 
diff --git a/gcc/rust/resolve/rust-ast-resolve-stmt.cc b/gcc/rust/resolve/rust-ast-resolve-stmt.cc
new file mode 100644
index 00000000000..6fc929f3e43
--- /dev/null
+++ b/gcc/rust/resolve/rust-ast-resolve-stmt.cc
@@ -0,0 +1,38 @@
+// Copyright (C) 2020-2022 Free Software Foundation, Inc.
+
+// This file is part of GCC.
+
+// GCC is free software; you can redistribute it and/or modify it under
+// the terms of the GNU General Public License as published by the Free
+// Software Foundation; either version 3, or (at your option) any later
+// version.
+
+// GCC is distributed in the hope that it will be useful, but WITHOUT ANY
+// WARRANTY; without even the implied warranty of MERCHANTABILITY or
+// FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+// for more details.
+
+// You should have received a copy of the GNU General Public License
+// along with GCC; see the file COPYING3.  If not see
+// <http://www.gnu.org/licenses/>.
+
+#include "rust-ast-resolve-item.h"
+#include "rust-ast-resolve-stmt.h"
+
+namespace Rust {
+namespace Resolver {
+
+void
+ResolveStmt::visit (AST::ExternBlock &extern_block)
+{
+  resolve_visibility (extern_block.get_visibility ());
+  for (auto &item : extern_block.get_extern_items ())
+    {
+      ResolveToplevelExternItem::go (item.get (),
+				     CanonicalPath::create_empty ());
+      ResolveExternItem::go (item.get ());
+    }
+}
+
+} // namespace Resolver
+} // namespace Rust
diff --git a/gcc/rust/resolve/rust-ast-resolve-stmt.h b/gcc/rust/resolve/rust-ast-resolve-stmt.h
index 3afed532afa..c8d42bcc7ca 100644
--- a/gcc/rust/resolve/rust-ast-resolve-stmt.h
+++ b/gcc/rust/resolve/rust-ast-resolve-stmt.h
@@ -406,6 +406,8 @@ public:
     resolver->get_label_scope ().pop ();
   }
 
+  void visit (AST::ExternBlock &extern_block) override;
+
 private:
   ResolveStmt (NodeId parent, const CanonicalPath &prefix,
 	       const CanonicalPath &canonical_prefix,
diff --git a/gcc/rust/typecheck/rust-hir-type-check-stmt.h b/gcc/rust/typecheck/rust-hir-type-check-stmt.h
index 2f14966ed66..b0ffd2a2157 100644
--- a/gcc/rust/typecheck/rust-hir-type-check-stmt.h
+++ b/gcc/rust/typecheck/rust-hir-type-check-stmt.h
@@ -24,6 +24,7 @@
 #include "rust-hir-type-check-type.h"
 #include "rust-hir-type-check-expr.h"
 #include "rust-hir-type-check-enumitem.h"
+#include "rust-hir-type-check-implitem.h"
 
 namespace Rust {
 namespace Resolver {
@@ -56,6 +57,14 @@ public:
       = TyTy::TupleType::get_unit_type (stmt.get_mappings ().get_hirid ());
   }
 
+  void visit (HIR::ExternBlock &extern_block) override
+  {
+    for (auto &item : extern_block.get_extern_items ())
+      {
+	TypeCheckTopLevelExternItem::Resolve (item.get (), extern_block);
+      }
+  }
+
   void visit (HIR::ConstantItem &constant) override
   {
     TyTy::BaseType *type = TypeCheckType::Resolve (constant.get_type ());
diff --git a/gcc/rust/typecheck/rust-hir-type-check.cc b/gcc/rust/typecheck/rust-hir-type-check.cc
index ee6663877a5..60531c0933d 100644
--- a/gcc/rust/typecheck/rust-hir-type-check.cc
+++ b/gcc/rust/typecheck/rust-hir-type-check.cc
@@ -90,12 +90,7 @@ TypeCheckExpr::visit (HIR::BlockExpr &expr)
       if (!s->is_item ())
 	continue;
 
-      auto resolved = TypeCheckStmt::Resolve (s.get (), inside_loop);
-      if (resolved == nullptr)
-	{
-	  rust_error_at (s->get_locus (), "failure to resolve type");
-	  return;
-	}
+      TypeCheckStmt::Resolve (s.get (), inside_loop);
     }
 
   for (auto &s : expr.get_statements ())
diff --git a/gcc/testsuite/rust/execute/torture/issue-976.rs b/gcc/testsuite/rust/execute/torture/issue-976.rs
new file mode 100644
index 00000000000..42cf596fb7d
--- /dev/null
+++ b/gcc/testsuite/rust/execute/torture/issue-976.rs
@@ -0,0 +1,14 @@
+/* { dg-output "hi" } */
+fn main() -> i32 {
+    {
+        extern "C" {
+            fn puts(s: *const i8);
+        }
+
+        unsafe {
+            puts("hi\0" as *const str as *const i8);
+        }
+    }
+
+    0
+}


^ permalink raw reply	[flat|nested] only message in thread

only message in thread, other threads:[~2022-06-08 12:47 UTC | newest]

Thread overview: (only message) (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2022-06-08 12:47 [gcc/devel/rust/master] Support extern-blocks defined within blocks Thomas Schwinge

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).