https://gcc.gnu.org/g:0f347d53597f8c325dcea34ee19749e1ddf429d2

commit r15-8342-g0f347d53597f8c325dcea34ee19749e1ddf429d2
Author: badumbatish <tanghocle...@gmail.com>
Date:   Sat Jul 6 13:17:00 2024 -0700

    gccrs: Successfully produce pseudo-nop
    
    gcc/rust/ChangeLog:
    
            * backend/rust-compile-asm.cc (CompileAsm::add_stmt):
            Deleted
            (CompileAsm::CompileAsm):
            Successfully produce pseudo-nop
            (CompileAsm::visit): Likewise
            (CompileAsm::asm_build_asm_stmt): Likewise
            (CompileAsm::asm_construct_string_tree): Likewise
            (CompileAsm::asm_is_inline): Likewise
            * backend/rust-compile-asm.h (class CompileAsm): Likewise
            * backend/rust-compile-expr.cc (CompileExpr::visit): Likewise

Diff:
---
 gcc/rust/backend/rust-compile-asm.cc  | 178 +++++++++++++++++++++++++++++-----
 gcc/rust/backend/rust-compile-asm.h   |  73 +++++++++++++-
 gcc/rust/backend/rust-compile-expr.cc |   3 +-
 3 files changed, 224 insertions(+), 30 deletions(-)

diff --git a/gcc/rust/backend/rust-compile-asm.cc 
b/gcc/rust/backend/rust-compile-asm.cc
index bc11696ed101..fe080f6aa6b9 100644
--- a/gcc/rust/backend/rust-compile-asm.cc
+++ b/gcc/rust/backend/rust-compile-asm.cc
@@ -2,34 +2,17 @@
 
 #include "rust-tree.h"
 #include "rust-system.h"
+#include <cstddef>
 namespace Rust {
 namespace Compile {
 
-tree
-CompileAsm::add_stmt (tree t)
+CompileAsm::CompileAsm (Context *ctx)
+  : HIRCompileBase (ctx), translated (error_mark_node)
+{}
+void
+CompileAsm::visit (HIR::InlineAsm &expr)
 {
-  enum tree_code code = TREE_CODE (t);
-
-  if (EXPR_P (t) && code != LABEL_EXPR)
-    {
-      if (!EXPR_HAS_LOCATION (t))
-       SET_EXPR_LOCATION (t, input_location);
-
-      /* When we expand a statement-tree, we must know whether or not the
-        statements are full-expressions.  We record that fact here.  */
-      if (STATEMENT_CODE_P (TREE_CODE (t)))
-       STMT_IS_FULL_EXPR_P (t) = stmts_are_full_exprs_p ();
-    }
-
-  if (code == LABEL_EXPR || code == CASE_LABEL_EXPR)
-    STATEMENT_LIST_HAS_LABEL (cur_stmt_list) = 1;
-
-  /* Add T to the statement-tree.  Non-side-effect statements need to be
-     recorded during statement expressions.  */
-  gcc_checking_assert (!stmt_list_stack->is_empty ());
-  append_to_statement_list_force (t, &cur_stmt_list);
-
-  return t;
+  return ctx->add_statement (asm_build_expr (expr));
 }
 tree
 CompileAsm::asm_build_asm_stmt (HIR::InlineAsm &expr)
@@ -43,7 +26,7 @@ CompileAsm::asm_build_asm_stmt (HIR::InlineAsm &expr)
   //   return add_stmt (args);
   // }
   //
-  return add_stmt (asm_build_expr (expr));
+  return NULL_TREE;
 }
 tree
 CompileAsm::asm_build_expr (HIR::InlineAsm &expr)
@@ -116,6 +99,8 @@ CompileAsm::asm_construct_string_tree (HIR::InlineAsm &expr)
 {
   if (expr.template_strs.empty ())
     return build_string (1, "");
+  else
+    return build_string (4, "nop");
   // Initialize to NULL_TREE
   tree string_chain = NULL_TREE;
 
@@ -168,3 +153,146 @@ CompileAsm::asm_is_inline (HIR::InlineAsm &expr)
 }
 } // namespace Compile
 } // namespace Rust
+  //
+  //
+  // The following section serves as documentation for PR revieweres and future
+  // asm developers. It documents the inspriation for the implementation of the
+  // CompileAsm class
+
+// From the implementation of c-typeck.cc
+// tree
+// build_asm_stmt (bool is_volatile, tree args)
+//{
+//   if (is_volatile)
+//     ASM_VOLATILE_P (args) = 1;
+//   return add_stmt (args);
+// }
+//
+///* Build an asm-expr, whose components are a STRING, some OUTPUTS,
+//   some INPUTS, and some CLOBBERS.  The latter three may be NULL.
+//   SIMPLE indicates whether there was anything at all after the
+//   string in the asm expression -- asm("blah") and asm("blah" : )
+//   are subtly different.  We use a ASM_EXPR node to represent this.
+//   LOC is the location of the asm, and IS_INLINE says whether this
+//   is asm inline.  */
+// tree
+// build_asm_expr (location_t loc, tree string, tree outputs, tree inputs,
+//             tree clobbers, tree labels, bool simple, bool is_inline)
+//{
+//  tree tail;
+//  tree args;
+//  int i;
+//  const char *constraint;
+//  const char **oconstraints;
+//  bool allows_mem, allows_reg, is_inout;
+//  int ninputs, noutputs;
+//
+//  ninputs = list_length (inputs);
+//  noutputs = list_length (outputs);
+//  oconstraints = (const char **) alloca (noutputs * sizeof (const char *));
+//
+//  string = resolve_asm_operand_names (string, outputs, inputs, labels);
+//
+//  /* Remove output conversions that change the type but not the mode.  */
+//  for (i = 0, tail = outputs; tail; ++i, tail = TREE_CHAIN (tail))
+//    {
+//      tree output = TREE_VALUE (tail);
+//
+//      output = c_fully_fold (output, false, NULL, true);
+//
+//      /* ??? Really, this should not be here.  Users should be using a
+//      proper lvalue, dammit.  But there's a long history of using casts
+//      in the output operands.  In cases like longlong.h, this becomes a
+//      primitive form of typechecking -- if the cast can be removed, then
+//      the output operand had a type of the proper width; otherwise we'll
+//      get an error.  Gross, but ...  */
+//      STRIP_NOPS (output);
+//
+//      if (!lvalue_or_else (loc, output, lv_asm))
+//     output = error_mark_node;
+//
+//      if (output != error_mark_node
+//       && (TREE_READONLY (output)
+//           || TYPE_READONLY (TREE_TYPE (output))
+//           || (RECORD_OR_UNION_TYPE_P (TREE_TYPE (output))
+//               && C_TYPE_FIELDS_READONLY (TREE_TYPE (output)))))
+//     readonly_error (loc, output, lv_asm);
+//
+//      constraint = TREE_STRING_POINTER (TREE_VALUE (TREE_PURPOSE (tail)));
+//      oconstraints[i] = constraint;
+//
+//      if (parse_output_constraint (&constraint, i, ninputs, noutputs,
+//                                &allows_mem, &allows_reg, &is_inout))
+//     {
+//       /* If the operand is going to end up in memory,
+//          mark it addressable.  */
+//       if (!allows_reg && !c_mark_addressable (output))
+//         output = error_mark_node;
+//       if (!(!allows_reg && allows_mem)
+//           && output != error_mark_node
+//           && VOID_TYPE_P (TREE_TYPE (output)))
+//         {
+//           error_at (loc, "invalid use of void expression");
+//           output = error_mark_node;
+//         }
+//     }
+//      else
+//     output = error_mark_node;
+//
+//      TREE_VALUE (tail) = output;
+//    }
+//
+//  for (i = 0, tail = inputs; tail; ++i, tail = TREE_CHAIN (tail))
+//    {
+//      tree input;
+//
+//      constraint = TREE_STRING_POINTER (TREE_VALUE (TREE_PURPOSE (tail)));
+//      input = TREE_VALUE (tail);
+//
+//      if (parse_input_constraint (&constraint, i, ninputs, noutputs, 0,
+//                               oconstraints, &allows_mem, &allows_reg))
+//     {
+//       /* If the operand is going to end up in memory,
+//          mark it addressable.  */
+//       if (!allows_reg && allows_mem)
+//         {
+//           input = c_fully_fold (input, false, NULL, true);
+//
+//           /* Strip the nops as we allow this case.  FIXME, this really
+//              should be rejected or made deprecated.  */
+//           STRIP_NOPS (input);
+//           if (!c_mark_addressable (input))
+//             input = error_mark_node;
+//         }
+//       else
+//         {
+//           struct c_expr expr;
+//           memset (&expr, 0, sizeof (expr));
+//           expr.value = input;
+//           expr = convert_lvalue_to_rvalue (loc, expr, true, false);
+//           input = c_fully_fold (expr.value, false, NULL);
+//
+//           if (input != error_mark_node && VOID_TYPE_P (TREE_TYPE (input)))
+//             {
+//               error_at (loc, "invalid use of void expression");
+//               input = error_mark_node;
+//             }
+//         }
+//     }
+//      else
+//     input = error_mark_node;
+//
+//      TREE_VALUE (tail) = input;
+//    }
+//
+//  args = build_stmt (loc, ASM_EXPR, string, outputs, inputs, clobbers,
+//  labels);
+//
+//  /* asm statements without outputs, including simple ones, are treated
+//     as volatile.  */
+//  ASM_INPUT_P (args) = simple;
+//  ASM_VOLATILE_P (args) = (noutputs == 0);
+//  ASM_INLINE_P (args) = is_inline;
+//
+//  return args;
+//}
diff --git a/gcc/rust/backend/rust-compile-asm.h 
b/gcc/rust/backend/rust-compile-asm.h
index fd25090cf982..d7967bc7fdb5 100644
--- a/gcc/rust/backend/rust-compile-asm.h
+++ b/gcc/rust/backend/rust-compile-asm.h
@@ -26,25 +26,90 @@
 namespace Rust {
 namespace Compile {
 
-class CompileAsm
+class CompileAsm : private HIRCompileBase, protected HIR::HIRExpressionVisitor
 {
 public:
+  // static tree Compile (HIR::Expr *expr, Context *ctx);
+
+  void visit (HIR::InlineAsm &expr) override;
+
+  void visit (HIR::TupleIndexExpr &expr) override {}
+  void visit (HIR::TupleExpr &expr) override {}
+  void visit (HIR::ReturnExpr &expr) override {}
+  void visit (HIR::CallExpr &expr) override {}
+  void visit (HIR::MethodCallExpr &expr) override {}
+  void visit (HIR::LiteralExpr &expr) override {}
+  void visit (HIR::AssignmentExpr &expr) override {}
+  void visit (HIR::CompoundAssignmentExpr &expr) override {}
+  void visit (HIR::ArrayIndexExpr &expr) override {}
+  void visit (HIR::ArrayExpr &expr) override {}
+  void visit (HIR::ArithmeticOrLogicalExpr &expr) override {}
+  void visit (HIR::ComparisonExpr &expr) override {}
+  void visit (HIR::LazyBooleanExpr &expr) override {}
+  void visit (HIR::NegationExpr &expr) override {}
+  void visit (HIR::TypeCastExpr &expr) override {}
+  void visit (HIR::IfExpr &expr) override {}
+  void visit (HIR::IfExprConseqElse &expr) override {}
+  void visit (HIR::BlockExpr &expr) override {}
+  void visit (HIR::UnsafeBlockExpr &expr) override {}
+  void visit (HIR::StructExprStruct &struct_expr) override {}
+  void visit (HIR::StructExprStructFields &struct_expr) override {}
+  void visit (HIR::GroupedExpr &expr) override {}
+  void visit (HIR::FieldAccessExpr &expr) override {}
+  void visit (HIR::QualifiedPathInExpression &expr) override {}
+  void visit (HIR::PathInExpression &expr) override {}
+  void visit (HIR::LoopExpr &expr) override {}
+  void visit (HIR::WhileLoopExpr &expr) override {}
+  void visit (HIR::BreakExpr &expr) override {}
+  void visit (HIR::ContinueExpr &expr) override {}
+  void visit (HIR::BorrowExpr &expr) override {}
+  void visit (HIR::DereferenceExpr &expr) override {}
+  void visit (HIR::MatchExpr &expr) override {}
+  void visit (HIR::RangeFromToExpr &expr) override {}
+  void visit (HIR::RangeFromExpr &expr) override {}
+  void visit (HIR::RangeToExpr &expr) override {}
+  void visit (HIR::RangeFullExpr &expr) override {}
+  void visit (HIR::RangeFromToInclExpr &expr) override {}
+  void visit (HIR::ClosureExpr &expr) override {}
+
+  // TODO
+  void visit (HIR::ErrorPropagationExpr &) override {}
+  void visit (HIR::RangeToInclExpr &) override {}
+
+  // 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 {}
+  void visit (HIR::AsyncBlockExpr &) override {}
+
+  // nothing to do for these
+  void visit (HIR::StructExprFieldIdentifier &) override {}
+  void visit (HIR::StructExprFieldIdentifierValue &) override {}
+  void visit (HIR::StructExprFieldIndexValue &) override {}
+
   static const int ASM_TREE_ARRAY_LENGTH = 5;
-  static tree add_stmt (tree);
   static tree asm_build_asm_stmt (HIR::InlineAsm &);
   static tree asm_build_expr (HIR::InlineAsm &);
   static tree asm_build_stmt (location_t, enum tree_code,
                              const std::array<tree, ASM_TREE_ARRAY_LENGTH> &);
+
   static location_t asm_get_locus (HIR::InlineAsm &);
   static tree asm_construct_string_tree (HIR::InlineAsm &);
   static tree asm_construct_outputs (HIR::InlineAsm &);
   static tree asm_construct_inputs (HIR::InlineAsm &);
   static tree asm_construct_clobber_tree (HIR::InlineAsm &);
   static tree asm_construct_label_tree (HIR::InlineAsm &);
-
   static bool asm_is_simple (HIR::InlineAsm &);
-
   static bool asm_is_inline (HIR::InlineAsm &);
+
+  CompileAsm (Context *ctx);
+
+private:
+  tree translated;
 };
 } // namespace Compile
 } // namespace Rust
diff --git a/gcc/rust/backend/rust-compile-expr.cc 
b/gcc/rust/backend/rust-compile-expr.cc
index b59ed4183e71..31f9809c9227 100644
--- a/gcc/rust/backend/rust-compile-expr.cc
+++ b/gcc/rust/backend/rust-compile-expr.cc
@@ -321,7 +321,8 @@ CompileExpr::visit (HIR::IfExpr &expr)
 void
 CompileExpr::visit (HIR::InlineAsm &expr)
 {
-  translated = CompileAsm::asm_build_expr (expr);
+  CompileAsm a (ctx);
+  a.visit (expr);
   // translated = build_asm_expr (0, NULL_TREE, NULL_TREE, NULL_TREE, 
NULL_TREE,
   //                  NULL_TREE, true, true);
   // CompileAsm::asm_build_expr (expr);

Reply via email to