]> git.ipfire.org Git - thirdparty/gcc.git/commitdiff
gccrs: Add input/output from inout and split in out
authorPierre-Emmanuel Patry <pierre-emmanuel.patry@embecosm.com>
Tue, 29 Jul 2025 11:48:17 +0000 (13:48 +0200)
committerArthur Cohen <arthur.cohen@embecosm.com>
Tue, 5 Aug 2025 14:36:58 +0000 (16:36 +0200)
Inline assembly was incomplete and input/output from inout or split in
out were not handled.

gcc/rust/ChangeLog:

* backend/rust-compile-asm.cc (get_out_expr): Return valid output from
an operand.
(CompileAsm::asm_construct_outputs): Handle every output
(get_in_expr): Return valid input from an operand.
(CompileAsm::asm_construct_inputs): Handle every input

Signed-off-by: Pierre-Emmanuel Patry <pierre-emmanuel.patry@embecosm.com>
gcc/rust/backend/rust-compile-asm.cc

index 7351cf0c5671a947b5f2dcab8dc33f919a5bac4b..b7143a817af5005b4b8a04ff2f50907303c57c31 100644 (file)
@@ -74,57 +74,94 @@ CompileAsm::asm_construct_string_tree (HIR::InlineAsm &expr)
   return Backend::string_constant_expression (result);
 }
 
+tl::optional<std::reference_wrapper<HIR::Expr>>
+get_out_expr (HIR::InlineAsmOperand &operand)
+{
+  switch (operand.get_register_type ())
+    {
+    case HIR::InlineAsmOperand::RegisterType::Out:
+      return *operand.get_out ().expr;
+    case HIR::InlineAsmOperand::RegisterType::InOut:
+      return *operand.get_in_out ().expr;
+    case HIR::InlineAsmOperand::RegisterType::SplitInOut:
+      return *operand.get_split_in_out ().out_expr;
+    case HIR::InlineAsmOperand::RegisterType::Const:
+    case HIR::InlineAsmOperand::RegisterType::Sym:
+    case HIR::InlineAsmOperand::RegisterType::Label:
+    case HIR::InlineAsmOperand::RegisterType::In:
+      break;
+    }
+  return tl::nullopt;
+}
+
 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 ())
+  for (auto &operand : 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);*/
-       }
+      tl::optional<std::reference_wrapper<HIR::Expr>> out_expr
+       = get_out_expr (operand);
+      if (!out_expr.has_value ())
+       continue;
+
+      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;
 }
 
+tl::optional<std::reference_wrapper<HIR::Expr>>
+get_in_expr (HIR::InlineAsmOperand &operand)
+{
+  switch (operand.get_register_type ())
+    {
+    case HIR::InlineAsmOperand::RegisterType::In:
+      return *operand.get_in ().expr;
+    case HIR::InlineAsmOperand::RegisterType::InOut:
+      return *operand.get_in_out ().expr;
+    case HIR::InlineAsmOperand::RegisterType::SplitInOut:
+      return *operand.get_split_in_out ().in_expr;
+    case HIR::InlineAsmOperand::RegisterType::Const:
+    case HIR::InlineAsmOperand::RegisterType::Sym:
+    case HIR::InlineAsmOperand::RegisterType::Label:
+    case HIR::InlineAsmOperand::RegisterType::Out:
+      break;
+    }
+  return tl::nullopt;
+}
+
 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 ())
+  for (auto &operand : 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);*/
-       }
+      tl::optional<std::reference_wrapper<HIR::Expr>> in_expr
+       = get_in_expr (operand);
+      if (!in_expr.has_value ())
+       continue;
+
+      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;
 }