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