]> git.lizzy.rs Git - rust.git/blob - src/librustc/middle/trans/asm.rs
librustc: Move inline asm stuff to different mod.
[rust.git] / src / librustc / middle / trans / asm.rs
1 // Copyright 2012 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 core::prelude::*;
16
17 use lib;
18 use middle::trans::build::*;
19 use middle::trans::callee;
20 use middle::trans::common::*;
21 use middle::ty;
22
23 use syntax::ast;
24 use syntax::ast::*;
25
26 // Take an inline assembly expression and splat it out via LLVM
27 pub fn trans_inline_asm(bcx: block, asm: @~str, ins: &[(@~str, @expr)], outs: &[(@~str, @expr)],
28                         clobs: @~str, volatile: bool, alignstack: bool) -> block {
29
30     let mut bcx = bcx;
31     let mut constraints = ~[];
32     let mut cleanups = ~[];
33     let mut aoutputs = ~[];
34
35     // Prepare the output operands
36     let outputs = do outs.map |&(c, out)| {
37         constraints.push(copy *c);
38
39         let aoutty = ty::arg {
40             mode: ast::expl(ast::by_copy),
41             ty: expr_ty(bcx, out)
42         };
43         aoutputs.push(unpack_result!(bcx, {
44             callee::trans_arg_expr(bcx, aoutty, out, &mut cleanups, None, callee::DontAutorefArg)
45         }));
46
47         let e = match out.node {
48             ast::expr_addr_of(_, e) => e,
49             _ => fail!(~"Expression must be addr of")
50         };
51
52         let outty = ty::arg {
53             mode: ast::expl(ast::by_copy),
54             ty: expr_ty(bcx, e)
55         };
56
57         unpack_result!(bcx, {
58             callee::trans_arg_expr(bcx, outty, e, &mut cleanups, None, callee::DontAutorefArg)
59         })
60
61     };
62
63     for cleanups.each |c| {
64         revoke_clean(bcx, *c);
65     }
66     cleanups.clear();
67
68     // Now the input operands
69     let inputs = do ins.map |&(c, in)| {
70         constraints.push(copy *c);
71
72         let inty = ty::arg {
73             mode: ast::expl(ast::by_copy),
74             ty: expr_ty(bcx, in)
75         };
76
77         unpack_result!(bcx, {
78             callee::trans_arg_expr(bcx, inty, in, &mut cleanups, None, callee::DontAutorefArg)
79         })
80
81     };
82
83     for cleanups.each |c| {
84         revoke_clean(bcx, *c);
85     }
86
87     let mut constraints = str::connect(constraints, ",");
88
89     // Add the clobbers to our constraints list
90     if *clobs != ~"" && constraints != ~"" {
91         constraints += ~"," + *clobs;
92     } else {
93         constraints += *clobs;
94     }
95
96     debug!("Asm Constraints: %?", constraints);
97
98     let numOutputs = outputs.len();
99
100     // Depending on how many outputs we have, the return type is different
101     let output = if numOutputs == 0 {
102         T_void()
103     } else if numOutputs == 1 {
104         val_ty(outputs[0])
105     } else {
106         T_struct(outputs.map(|o| val_ty(*o)))
107     };
108
109     let r = do str::as_c_str(*asm) |a| {
110         do str::as_c_str(constraints) |c| {
111             // XXX: Allow selection of at&t or intel
112             InlineAsmCall(bcx, a, c, inputs, output, volatile, alignstack, lib::llvm::AD_ATT)
113         }
114     };
115
116     // Again, based on how many outputs we have 
117     if numOutputs == 1 {
118         let op = PointerCast(bcx, aoutputs[0], T_ptr(val_ty(outputs[0])));
119         Store(bcx, r, op);
120     } else {
121         for aoutputs.eachi |i, o| {
122             let v = ExtractValue(bcx, r, i);
123             let op = PointerCast(bcx, *o, T_ptr(val_ty(outputs[i])));
124             Store(bcx, v, op);
125         }
126     }
127
128     return bcx;
129
130 }