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.
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.
12 # Translation of inline assembly.
18 use middle::trans::build::*;
19 use middle::trans::callee;
20 use middle::trans::common::*;
25 // Take an inline assembly expression and splat it out via LLVM
26 pub fn trans_inline_asm(bcx: block, ia: &ast::inline_asm) -> block {
29 let mut constraints = ~[];
30 let mut cleanups = ~[];
31 let mut aoutputs = ~[];
33 // Prepare the output operands
34 let outputs = do ia.outputs.map |&(c, out)| {
35 constraints.push(copy *c);
37 let aoutty = ty::arg {
38 mode: ast::expl(ast::by_copy),
41 aoutputs.push(unpack_result!(bcx, {
42 callee::trans_arg_expr(bcx, aoutty, out, &mut cleanups, None, callee::DontAutorefArg)
45 let e = match out.node {
46 ast::expr_addr_of(_, e) => e,
47 _ => fail!(~"Expression must be addr of")
51 mode: ast::expl(ast::by_copy),
56 callee::trans_arg_expr(bcx, outty, e, &mut cleanups, None, callee::DontAutorefArg)
61 for cleanups.each |c| {
62 revoke_clean(bcx, *c);
66 // Now the input operands
67 let inputs = do ia.inputs.map |&(c, in)| {
68 constraints.push(copy *c);
71 mode: ast::expl(ast::by_copy),
76 callee::trans_arg_expr(bcx, inty, in, &mut cleanups, None, callee::DontAutorefArg)
81 for cleanups.each |c| {
82 revoke_clean(bcx, *c);
85 let mut constraints = str::connect(constraints, ",");
87 // Add the clobbers to our constraints list
88 if *ia.clobbers != ~"" && constraints != ~"" {
89 constraints += ~"," + *ia.clobbers;
91 constraints += *ia.clobbers;
94 debug!("Asm Constraints: %?", constraints);
96 let numOutputs = outputs.len();
98 // Depending on how many outputs we have, the return type is different
99 let output = if numOutputs == 0 {
101 } else if numOutputs == 1 {
104 T_struct(outputs.map(|o| val_ty(*o)))
107 let dialect = match ia.dialect {
108 ast::asm_att => lib::llvm::AD_ATT,
109 ast::asm_intel => lib::llvm::AD_Intel
112 let r = do str::as_c_str(*ia.asm) |a| {
113 do str::as_c_str(constraints) |c| {
114 // XXX: Allow selection of at&t or intel
115 InlineAsmCall(bcx, a, c, inputs, output, ia.volatile, ia.alignstack, dialect)
119 // Again, based on how many outputs we have
121 let op = PointerCast(bcx, aoutputs[0], T_ptr(val_ty(outputs[0])));
124 for aoutputs.eachi |i, o| {
125 let v = ExtractValue(bcx, r, i);
126 let op = PointerCast(bcx, *o, T_ptr(val_ty(outputs[i])));