]> git.lizzy.rs Git - rust.git/blob - src/librustc/middle/trans/asm.rs
librustc: Fix errors arising from the automated `~[T]` conversion
[rust.git] / src / librustc / middle / trans / asm.rs
1 // Copyright 2012-2013 The Rust Project Developers. See the COPYRIGHT
2 // file at the top-level directory of this distribution and at
3 // http://rust-lang.org/COPYRIGHT.
4 //
5 // Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
6 // http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
7 // <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
8 // option. This file may not be copied, modified, or distributed
9 // except according to those terms.
10
11 /*!
12 # Translation of inline assembly.
13 */
14
15 use std::c_str::ToCStr;
16
17 use lib;
18 use middle::trans::build::*;
19 use middle::trans::callee;
20 use middle::trans::common::*;
21 use middle::trans::cleanup;
22 use middle::trans::cleanup::CleanupMethods;
23 use middle::trans::expr;
24 use middle::trans::type_of;
25
26 use middle::trans::type_::Type;
27
28 use syntax::ast;
29
30 // Take an inline assembly expression and splat it out via LLVM
31 pub fn trans_inline_asm<'a>(bcx: &'a Block<'a>, ia: &ast::InlineAsm)
32                         -> &'a Block<'a> {
33     let fcx = bcx.fcx;
34     let mut bcx = bcx;
35     let mut constraints = ~[];
36     let mut output_types = ~[];
37
38     let temp_scope = fcx.push_custom_cleanup_scope();
39
40     // Prepare the output operands
41     let outputs = ia.outputs.map(|&(ref c, out)| {
42         constraints.push((*c).clone());
43
44         let out_datum = unpack_datum!(bcx, expr::trans(bcx, out));
45         output_types.push(type_of::type_of(bcx.ccx(), out_datum.ty));
46         out_datum.val
47
48     });
49
50     // Now the input operands
51     let inputs = ia.inputs.map(|&(ref c, input)| {
52         constraints.push((*c).clone());
53
54         unpack_result!(bcx, {
55             callee::trans_arg_expr(bcx,
56                                    expr_ty(bcx, input),
57                                    input,
58                                    cleanup::CustomScope(temp_scope),
59                                    callee::DontAutorefArg)
60         })
61     });
62
63     // no failure occurred preparing operands, no need to cleanup
64     fcx.pop_custom_cleanup_scope(temp_scope);
65
66     let mut constraints = constraints.map(|s| s.get().to_str()).connect(",");
67
68     let mut clobbers = getClobbers();
69     if !ia.clobbers.get().is_empty() && !clobbers.is_empty() {
70         clobbers = format!("{},{}", ia.clobbers.get(), clobbers);
71     } else {
72         clobbers.push_str(ia.clobbers.get());
73     }
74
75     // Add the clobbers to our constraints list
76     if clobbers.len() != 0 && constraints.len() != 0 {
77         constraints.push_char(',');
78         constraints.push_str(clobbers);
79     } else {
80         constraints.push_str(clobbers);
81     }
82
83     debug!("Asm Constraints: {:?}", constraints);
84
85     let numOutputs = outputs.len();
86
87     // Depending on how many outputs we have, the return type is different
88     let output_type = if numOutputs == 0 {
89         Type::void()
90     } else if numOutputs == 1 {
91         output_types[0]
92     } else {
93         Type::struct_(output_types, false)
94     };
95
96     let dialect = match ia.dialect {
97         ast::AsmAtt   => lib::llvm::AD_ATT,
98         ast::AsmIntel => lib::llvm::AD_Intel
99     };
100
101     let r = ia.asm.get().with_c_str(|a| {
102         constraints.with_c_str(|c| {
103             InlineAsmCall(bcx,
104                           a,
105                           c,
106                           inputs.as_slice(),
107                           output_type,
108                           ia.volatile,
109                           ia.alignstack,
110                           dialect)
111         })
112     });
113
114     // Again, based on how many outputs we have
115     if numOutputs == 1 {
116         Store(bcx, r, *outputs.get(0));
117     } else {
118         for (i, o) in outputs.iter().enumerate() {
119             let v = ExtractValue(bcx, r, i);
120             Store(bcx, v, *o);
121         }
122     }
123
124     return bcx;
125
126 }
127
128 // Default per-arch clobbers
129 // Basically what clang does
130
131 #[cfg(target_arch = "arm")]
132 #[cfg(target_arch = "mips")]
133 fn getClobbers() -> ~str {
134     ~""
135 }
136
137 #[cfg(target_arch = "x86")]
138 #[cfg(target_arch = "x86_64")]
139 fn getClobbers() -> ~str {
140     ~"~{dirflag},~{fpsr},~{flags}"
141 }