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 : 26 : CompileAsm::CompileAsm (Context *ctx) : HIRCompileBase (ctx) {}
9 : :
10 : : tree
11 : 26 : CompileAsm::tree_codegen_asm (HIR::InlineAsm &expr)
12 : : {
13 : 26 : auto asm_expr
14 : 52 : = asm_build_stmt (expr.get_locus (), {asm_construct_string_tree (expr),
15 : 26 : asm_construct_outputs (expr),
16 : 26 : asm_construct_inputs (expr),
17 : 26 : asm_construct_clobber_tree (expr),
18 : 26 : asm_construct_label_tree (expr)});
19 : :
20 : 26 : ASM_BASIC_P (asm_expr) = expr.is_simple_asm ();
21 : 26 : ASM_VOLATILE_P (asm_expr) = false;
22 : 26 : ASM_INLINE_P (asm_expr) = expr.is_inline_asm ();
23 : : /*Backend::debug (asm_expr);*/
24 : 26 : return asm_expr;
25 : : }
26 : :
27 : : tree
28 : 26 : 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 : 26 : tree ret;
34 : 26 : bool side_effects;
35 : :
36 : 26 : ret = make_node (ASM_EXPR);
37 : 26 : TREE_TYPE (ret) = void_type_node;
38 : 26 : 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 : 26 : side_effects = false;
48 : 156 : for (size_t i = 0; i < trees.size (); i++)
49 : : {
50 : 130 : tree t = trees[i];
51 : 130 : if (t && !TYPE_P (t))
52 : 56 : side_effects |= TREE_SIDE_EFFECTS (t);
53 : 130 : TREE_OPERAND (ret, i) = t;
54 : : }
55 : :
56 : 26 : TREE_SIDE_EFFECTS (ret) |= side_effects;
57 : :
58 : 26 : return ret;
59 : : }
60 : :
61 : : tree
62 : 26 : 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 : 26 : std::stringstream ss;
70 : 52 : for (const auto &template_str : expr.template_strs)
71 : 52 : ss << template_str.symbol << "\n";
72 : :
73 : 26 : std::string result = ss.str ();
74 : 26 : return Backend::string_constant_expression (result);
75 : 26 : }
76 : :
77 : : tl::optional<std::reference_wrapper<HIR::Expr>>
78 : 29 : get_out_expr (HIR::InlineAsmOperand &operand)
79 : : {
80 : 29 : switch (operand.get_register_type ())
81 : : {
82 : 17 : case HIR::InlineAsmOperand::RegisterType::Out:
83 : 17 : return *operand.get_out ().expr;
84 : 0 : case HIR::InlineAsmOperand::RegisterType::InOut:
85 : 0 : return *operand.get_in_out ().expr;
86 : 2 : case HIR::InlineAsmOperand::RegisterType::SplitInOut:
87 : 2 : return *operand.get_split_in_out ().out_expr;
88 : : case HIR::InlineAsmOperand::RegisterType::Const:
89 : : case HIR::InlineAsmOperand::RegisterType::Sym:
90 : : case HIR::InlineAsmOperand::RegisterType::Label:
91 : : case HIR::InlineAsmOperand::RegisterType::In:
92 : : break;
93 : : }
94 : 10 : return tl::nullopt;
95 : : }
96 : :
97 : : tree
98 : 26 : CompileAsm::asm_construct_outputs (HIR::InlineAsm &expr)
99 : : {
100 : : // TODO: Do i need to do this?
101 : :
102 : 26 : tree head = NULL_TREE;
103 : 55 : for (auto &operand : expr.get_operands ())
104 : : {
105 : 29 : tl::optional<std::reference_wrapper<HIR::Expr>> out_expr
106 : 29 : = get_out_expr (operand);
107 : 29 : if (!out_expr.has_value ())
108 : 10 : continue;
109 : :
110 : 19 : tree out_tree = CompileExpr::Compile (*out_expr, this->ctx);
111 : : // expects a tree list
112 : : // TODO: This assumes that the output is a register
113 : 19 : std::string expr_name = "=r";
114 : 19 : auto name = build_string (expr_name.size () + 1, expr_name.c_str ());
115 : 19 : head = chainon (head, build_tree_list (build_tree_list (NULL_TREE, name),
116 : : out_tree));
117 : :
118 : : /*Backend::debug (head);*/
119 : : /*head = chainon (head, out_tree);*/
120 : 19 : }
121 : 26 : return head;
122 : : }
123 : :
124 : : tl::optional<std::reference_wrapper<HIR::Expr>>
125 : 29 : get_in_expr (HIR::InlineAsmOperand &operand)
126 : : {
127 : 29 : switch (operand.get_register_type ())
128 : : {
129 : 10 : case HIR::InlineAsmOperand::RegisterType::In:
130 : 10 : return *operand.get_in ().expr;
131 : 0 : case HIR::InlineAsmOperand::RegisterType::InOut:
132 : 0 : return *operand.get_in_out ().expr;
133 : 2 : case HIR::InlineAsmOperand::RegisterType::SplitInOut:
134 : 2 : return *operand.get_split_in_out ().in_expr;
135 : : case HIR::InlineAsmOperand::RegisterType::Const:
136 : : case HIR::InlineAsmOperand::RegisterType::Sym:
137 : : case HIR::InlineAsmOperand::RegisterType::Label:
138 : : case HIR::InlineAsmOperand::RegisterType::Out:
139 : : break;
140 : : }
141 : 17 : return tl::nullopt;
142 : : }
143 : :
144 : : tree
145 : 26 : CompileAsm::asm_construct_inputs (HIR::InlineAsm &expr)
146 : : {
147 : : // TODO: Do i need to do this?
148 : 26 : tree head = NULL_TREE;
149 : 55 : for (auto &operand : expr.get_operands ())
150 : : {
151 : 29 : tl::optional<std::reference_wrapper<HIR::Expr>> in_expr
152 : 29 : = get_in_expr (operand);
153 : 29 : if (!in_expr.has_value ())
154 : 17 : continue;
155 : :
156 : 12 : tree in_tree = CompileExpr::Compile (*in_expr, this->ctx);
157 : : // expects a tree list
158 : : // TODO: This assumes that the input is a register
159 : 12 : std::string expr_name = "r";
160 : 12 : auto name = build_string (expr_name.size () + 1, expr_name.c_str ());
161 : 12 : head = chainon (head, build_tree_list (build_tree_list (NULL_TREE, name),
162 : : in_tree));
163 : :
164 : : /*head = chainon (head, out_tree);*/
165 : 12 : }
166 : 26 : return head;
167 : : }
168 : :
169 : : tree
170 : 26 : CompileAsm::asm_construct_clobber_tree (HIR::InlineAsm &expr)
171 : : {
172 : : // TODO: Do i need to do this?
173 : 26 : return NULL_TREE;
174 : : }
175 : :
176 : : tree
177 : 26 : CompileAsm::asm_construct_label_tree (HIR::InlineAsm &expr)
178 : : {
179 : : // TODO: Do i need to do this?
180 : 26 : return NULL_TREE;
181 : : }
182 : :
183 : 2 : CompileLlvmAsm::CompileLlvmAsm (Context *ctx) : HIRCompileBase (ctx) {}
184 : :
185 : : tree
186 : 4 : CompileLlvmAsm::construct_operands (std::vector<HIR::LlvmOperand> operands)
187 : : {
188 : 4 : tree head = NULL_TREE;
189 : 6 : for (auto &operand : operands)
190 : : {
191 : 2 : tree t = CompileExpr::Compile (*operand.expr, this->ctx);
192 : 2 : auto name = build_string (operand.constraint.size () + 1,
193 : : operand.constraint.c_str ());
194 : 2 : head = chainon (head,
195 : : build_tree_list (build_tree_list (NULL_TREE, name), t));
196 : : }
197 : 4 : return head;
198 : : }
199 : :
200 : : tree
201 : 2 : CompileLlvmAsm::construct_clobbers (std::vector<AST::TupleClobber> clobbers)
202 : : {
203 : 2 : tree head = NULL_TREE;
204 : 4 : for (auto &clobber : clobbers)
205 : : {
206 : 2 : auto name
207 : 2 : = build_string (clobber.symbol.size () + 1, clobber.symbol.c_str ());
208 : 2 : head = chainon (head, build_tree_list (NULL_TREE, name));
209 : : }
210 : 2 : return head;
211 : : }
212 : :
213 : : tree
214 : 2 : CompileLlvmAsm::tree_codegen_asm (HIR::LlvmInlineAsm &expr)
215 : : {
216 : 2 : tree ret = make_node (ASM_EXPR);
217 : 2 : TREE_TYPE (ret) = void_type_node;
218 : 2 : SET_EXPR_LOCATION (ret, expr.get_locus ());
219 : 2 : ASM_VOLATILE_P (ret) = expr.options.is_volatile;
220 : :
221 : 2 : std::stringstream ss;
222 : 4 : for (const auto &template_str : expr.templates)
223 : : {
224 : 4 : ss << template_str.symbol << "\n";
225 : : }
226 : :
227 : 2 : ASM_STRING (ret) = Backend::string_constant_expression (ss.str ());
228 : 2 : ASM_INPUTS (ret) = construct_operands (expr.inputs);
229 : 2 : ASM_OUTPUTS (ret) = construct_operands (expr.outputs);
230 : 2 : ASM_CLOBBERS (ret) = construct_clobbers (expr.get_clobbers ());
231 : :
232 : 4 : return ret;
233 : 2 : }
234 : :
235 : : } // namespace Compile
236 : : } // namespace Rust
|