LCOV - code coverage report
Current view: top level - gcc/rust/backend - rust-compile-asm.cc (source / functions) Coverage Total Hit
Test: gcc.info Lines: 96.3 % 108 104
Test Date: 2026-02-28 14:20:25 Functions: 100.0 % 15 15
Legend: Lines:     hit not hit

            Line data    Source code
       1              : #include "rust-compile-asm.h"
       2              : #include "rust-compile-expr.h"
       3              : #include "rust-system.h"
       4              : 
       5              : namespace Rust {
       6              : namespace Compile {
       7              : 
       8              : static tree
       9           31 : chain_asm_operand (tree head, const char *constraint, tree value)
      10              : {
      11           31 :   auto name = build_string (strlen (constraint) + 1, constraint);
      12           31 :   return chainon (head,
      13           31 :                   build_tree_list (build_tree_list (NULL_TREE, name), value));
      14              : }
      15              : 
      16           26 : CompileAsm::CompileAsm (Context *ctx) : HIRCompileBase (ctx) {}
      17              : 
      18              : tree
      19           26 : CompileAsm::tree_codegen_asm (HIR::InlineAsm &expr)
      20              : {
      21           26 :   auto asm_expr
      22           52 :     = asm_build_stmt (expr.get_locus (), {asm_construct_string_tree (expr),
      23           26 :                                           asm_construct_outputs (expr),
      24           26 :                                           asm_construct_inputs (expr),
      25           26 :                                           asm_construct_clobber_tree (expr),
      26           26 :                                           asm_construct_label_tree (expr)});
      27              : 
      28           26 :   ASM_BASIC_P (asm_expr) = expr.is_simple_asm ();
      29           26 :   ASM_VOLATILE_P (asm_expr) = false;
      30           26 :   ASM_INLINE_P (asm_expr) = expr.is_inline_asm ();
      31              :   /*Backend::debug (asm_expr);*/
      32           26 :   return asm_expr;
      33              : }
      34              : 
      35              : tree
      36           26 : CompileAsm::asm_build_stmt (
      37              :   location_t loc,
      38              :   const std::array<tree, CompileAsm::ASM_TREE_ARRAY_LENGTH> &trees)
      39              : {
      40              :   // Prototype functiion for building an ASM_EXPR tree.
      41           26 :   tree ret;
      42           26 :   bool side_effects;
      43              : 
      44           26 :   ret = make_node (ASM_EXPR);
      45           26 :   TREE_TYPE (ret) = void_type_node;
      46           26 :   SET_EXPR_LOCATION (ret, loc);
      47              : 
      48              :   /* TREE_SIDE_EFFECTS will already be set for statements with
      49              :      implicit side effects.  Here we make sure it is set for other
      50              :      expressions by checking whether the parameters have side
      51              :      effects.  */
      52              : 
      53              :   // This is here because of c-typeck.cc's code
      54              :   // I'm not sure what kind of effects it has
      55           26 :   side_effects = false;
      56          156 :   for (size_t i = 0; i < trees.size (); i++)
      57              :     {
      58          130 :       tree t = trees[i];
      59          130 :       if (t && !TYPE_P (t))
      60           56 :         side_effects |= TREE_SIDE_EFFECTS (t);
      61          130 :       TREE_OPERAND (ret, i) = t;
      62              :     }
      63              : 
      64           26 :   TREE_SIDE_EFFECTS (ret) |= side_effects;
      65              : 
      66           26 :   return ret;
      67              : }
      68              : 
      69              : tree
      70           26 : CompileAsm::asm_construct_string_tree (HIR::InlineAsm &expr)
      71              : {
      72              :   // To construct an ASM_EXPR tree, we need to build a STRING_CST tree.
      73              :   //
      74              :   // We do this by concatenating all the template strings in the InlineAsm
      75              :   // into one big std::string seperated by tabs and newlines. (For easier
      76              :   // debugging and reading)
      77           26 :   std::stringstream ss;
      78           52 :   for (const auto &template_str : expr.template_strs)
      79           52 :     ss << template_str.symbol << "\n";
      80              : 
      81           26 :   std::string result = ss.str ();
      82           26 :   return Backend::string_constant_expression (result);
      83           26 : }
      84              : 
      85              : tl::optional<std::reference_wrapper<HIR::Expr>>
      86           29 : get_out_expr (HIR::InlineAsmOperand &operand)
      87              : {
      88           29 :   switch (operand.get_register_type ())
      89              :     {
      90           17 :     case HIR::InlineAsmOperand::RegisterType::Out:
      91           17 :       return *operand.get_out ().expr;
      92            0 :     case HIR::InlineAsmOperand::RegisterType::InOut:
      93            0 :       return *operand.get_in_out ().expr;
      94            2 :     case HIR::InlineAsmOperand::RegisterType::SplitInOut:
      95            2 :       return *operand.get_split_in_out ().out_expr;
      96              :     case HIR::InlineAsmOperand::RegisterType::Const:
      97              :     case HIR::InlineAsmOperand::RegisterType::Sym:
      98              :     case HIR::InlineAsmOperand::RegisterType::Label:
      99              :     case HIR::InlineAsmOperand::RegisterType::In:
     100              :       break;
     101              :     }
     102           10 :   return tl::nullopt;
     103              : }
     104              : 
     105              : tree
     106           26 : CompileAsm::asm_construct_outputs (HIR::InlineAsm &expr)
     107              : {
     108              :   // TODO: Do i need to do this?
     109              : 
     110           26 :   tree head = NULL_TREE;
     111           55 :   for (auto &operand : expr.get_operands ())
     112              :     {
     113           29 :       tl::optional<std::reference_wrapper<HIR::Expr>> out_expr
     114           29 :         = get_out_expr (operand);
     115           29 :       if (!out_expr.has_value ())
     116           10 :         continue;
     117              : 
     118           19 :       tree out_tree = CompileExpr::Compile (*out_expr, this->ctx);
     119              :       // expects a tree list
     120              :       // TODO: This assumes that the output is a register
     121           19 :       head = chain_asm_operand (head, "=r", out_tree);
     122              :     }
     123           26 :   return head;
     124              : }
     125              : 
     126              : tl::optional<std::reference_wrapper<HIR::Expr>>
     127           29 : get_in_expr (HIR::InlineAsmOperand &operand)
     128              : {
     129           29 :   switch (operand.get_register_type ())
     130              :     {
     131           10 :     case HIR::InlineAsmOperand::RegisterType::In:
     132           10 :       return *operand.get_in ().expr;
     133            0 :     case HIR::InlineAsmOperand::RegisterType::InOut:
     134            0 :       return *operand.get_in_out ().expr;
     135            2 :     case HIR::InlineAsmOperand::RegisterType::SplitInOut:
     136            2 :       return *operand.get_split_in_out ().in_expr;
     137              :     case HIR::InlineAsmOperand::RegisterType::Const:
     138              :     case HIR::InlineAsmOperand::RegisterType::Sym:
     139              :     case HIR::InlineAsmOperand::RegisterType::Label:
     140              :     case HIR::InlineAsmOperand::RegisterType::Out:
     141              :       break;
     142              :     }
     143           17 :   return tl::nullopt;
     144              : }
     145              : 
     146              : tree
     147           26 : CompileAsm::asm_construct_inputs (HIR::InlineAsm &expr)
     148              : {
     149              :   // TODO: Do i need to do this?
     150           26 :   tree head = NULL_TREE;
     151           55 :   for (auto &operand : expr.get_operands ())
     152              :     {
     153           29 :       tl::optional<std::reference_wrapper<HIR::Expr>> in_expr
     154           29 :         = get_in_expr (operand);
     155           29 :       if (!in_expr.has_value ())
     156           17 :         continue;
     157              : 
     158           12 :       tree in_tree = CompileExpr::Compile (*in_expr, this->ctx);
     159              :       // expects a tree list
     160              :       // TODO: This assumes that the input is a register
     161           12 :       head = chain_asm_operand (head, "r", in_tree);
     162              :     }
     163           26 :   return head;
     164              : }
     165              : 
     166              : tree
     167           26 : CompileAsm::asm_construct_clobber_tree (HIR::InlineAsm &expr)
     168              : {
     169              :   // TODO: Do i need to do this?
     170           26 :   return NULL_TREE;
     171              : }
     172              : 
     173              : tree
     174           26 : CompileAsm::asm_construct_label_tree (HIR::InlineAsm &expr)
     175              : {
     176              :   // TODO: Do i need to do this?
     177           26 :   return NULL_TREE;
     178              : }
     179              : 
     180            2 : CompileLlvmAsm::CompileLlvmAsm (Context *ctx) : HIRCompileBase (ctx) {}
     181              : 
     182              : tree
     183            4 : CompileLlvmAsm::construct_operands (std::vector<HIR::LlvmOperand> operands)
     184              : {
     185            4 :   tree head = NULL_TREE;
     186            6 :   for (auto &operand : operands)
     187              :     {
     188            2 :       tree t = CompileExpr::Compile (*operand.expr, this->ctx);
     189            2 :       auto name = build_string (operand.constraint.size () + 1,
     190              :                                 operand.constraint.c_str ());
     191            2 :       head = chainon (head,
     192              :                       build_tree_list (build_tree_list (NULL_TREE, name), t));
     193              :     }
     194            4 :   return head;
     195              : }
     196              : 
     197              : tree
     198            2 : CompileLlvmAsm::construct_clobbers (std::vector<AST::TupleClobber> clobbers)
     199              : {
     200            2 :   tree head = NULL_TREE;
     201            4 :   for (auto &clobber : clobbers)
     202              :     {
     203            2 :       auto name
     204            2 :         = build_string (clobber.symbol.size () + 1, clobber.symbol.c_str ());
     205            2 :       head = chainon (head, build_tree_list (NULL_TREE, name));
     206              :     }
     207            2 :   return head;
     208              : }
     209              : 
     210              : tree
     211            2 : CompileLlvmAsm::tree_codegen_asm (HIR::LlvmInlineAsm &expr)
     212              : {
     213            2 :   tree ret = make_node (ASM_EXPR);
     214            2 :   TREE_TYPE (ret) = void_type_node;
     215            2 :   SET_EXPR_LOCATION (ret, expr.get_locus ());
     216            2 :   ASM_VOLATILE_P (ret) = expr.options.is_volatile;
     217              : 
     218            2 :   std::stringstream ss;
     219            4 :   for (const auto &template_str : expr.templates)
     220              :     {
     221            4 :       ss << template_str.symbol << "\n";
     222              :     }
     223              : 
     224            2 :   ASM_STRING (ret) = Backend::string_constant_expression (ss.str ());
     225            2 :   ASM_INPUTS (ret) = construct_operands (expr.inputs);
     226            2 :   ASM_OUTPUTS (ret) = construct_operands (expr.outputs);
     227            2 :   ASM_CLOBBERS (ret) = construct_clobbers (expr.get_clobbers ());
     228              : 
     229            4 :   return ret;
     230            2 : }
     231              : 
     232              : } // namespace Compile
     233              : } // namespace Rust
        

Generated by: LCOV version 2.4-beta

LCOV profile is generated on x86_64 machine using following configure options: configure --disable-bootstrap --enable-coverage=opt --enable-languages=c,c++,fortran,go,jit,lto,rust,m2 --enable-host-shared. GCC test suite is run with the built compiler.