https://gcc.gnu.org/g:68287a532c09dca6ef0c473db726ff385d0e7edb
commit r16-2964-g68287a532c09dca6ef0c473db726ff385d0e7edb Author: Pierre-Emmanuel Patry <pierre-emmanuel.pa...@embecosm.com> Date: Tue Jul 29 13:48:17 2025 +0200 gccrs: Add input/output from inout and split in out 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.pa...@embecosm.com> Diff: --- gcc/rust/backend/rust-compile-asm.cc | 105 +++++++++++++++++++++++------------ 1 file changed, 71 insertions(+), 34 deletions(-) diff --git a/gcc/rust/backend/rust-compile-asm.cc b/gcc/rust/backend/rust-compile-asm.cc index 7351cf0c5671..b7143a817af5 100644 --- a/gcc/rust/backend/rust-compile-asm.cc +++ b/gcc/rust/backend/rust-compile-asm.cc @@ -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; }