Skip to content

Commit f814592

Browse files
committed
auto merge of #5593 : luqmana/rust/inline-asm, r=catamorphism
Clean things up a bit. Also, allow selecting intel syntax in addition to the default AT&T dialect.
2 parents 943d7ad + a3996c1 commit f814592

File tree

11 files changed

+226
-138
lines changed

11 files changed

+226
-138
lines changed

Diff for: src/librustc/middle/liveness.rs

+12-7
Original file line numberDiff line numberDiff line change
@@ -1306,11 +1306,11 @@ pub impl Liveness {
13061306
self.propagate_through_expr(e, succ)
13071307
}
13081308

1309-
expr_inline_asm(_, ref ins, ref outs, _, _, _) =>{
1310-
let succ = do ins.foldr(succ) |&(_, expr), succ| {
1309+
expr_inline_asm(ref ia) =>{
1310+
let succ = do ia.inputs.foldr(succ) |&(_, expr), succ| {
13111311
self.propagate_through_expr(expr, succ)
13121312
};
1313-
do outs.foldr(succ) |&(_, expr), succ| {
1313+
do ia.outputs.foldr(succ) |&(_, expr), succ| {
13141314
self.propagate_through_expr(expr, succ)
13151315
}
13161316
}
@@ -1580,14 +1580,19 @@ fn check_expr(expr: @expr, &&self: @Liveness, vt: vt<@Liveness>) {
15801580
visit::visit_expr(expr, self, vt);
15811581
}
15821582

1583-
expr_inline_asm(_, ref ins, ref outs, _, _, _) => {
1584-
for ins.each |&(_, in)| {
1583+
expr_inline_asm(ref ia) => {
1584+
for ia.inputs.each |&(_, in)| {
15851585
(vt.visit_expr)(in, self, vt);
15861586
}
15871587

15881588
// Output operands must be lvalues
1589-
for outs.each |&(_, out)| {
1590-
self.check_lvalue(out, vt);
1589+
for ia.outputs.each |&(_, out)| {
1590+
match out.node {
1591+
expr_addr_of(_, inner) => {
1592+
self.check_lvalue(inner, vt);
1593+
}
1594+
_ => {}
1595+
}
15911596
(vt.visit_expr)(out, self, vt);
15921597
}
15931598

Diff for: src/librustc/middle/trans/asm.rs

+154
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,154 @@
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+
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 {
27+
28+
let mut bcx = bcx;
29+
let mut constraints = ~[];
30+
let mut cleanups = ~[];
31+
let mut aoutputs = ~[];
32+
33+
// Prepare the output operands
34+
let outputs = do ia.outputs.map |&(c, out)| {
35+
constraints.push(copy *c);
36+
37+
let aoutty = ty::arg {
38+
mode: ast::expl(ast::by_copy),
39+
ty: expr_ty(bcx, out)
40+
};
41+
aoutputs.push(unpack_result!(bcx, {
42+
callee::trans_arg_expr(bcx, aoutty, out, &mut cleanups, None, callee::DontAutorefArg)
43+
}));
44+
45+
let e = match out.node {
46+
ast::expr_addr_of(_, e) => e,
47+
_ => fail!(~"Expression must be addr of")
48+
};
49+
50+
let outty = ty::arg {
51+
mode: ast::expl(ast::by_copy),
52+
ty: expr_ty(bcx, e)
53+
};
54+
55+
unpack_result!(bcx, {
56+
callee::trans_arg_expr(bcx, outty, e, &mut cleanups, None, callee::DontAutorefArg)
57+
})
58+
59+
};
60+
61+
for cleanups.each |c| {
62+
revoke_clean(bcx, *c);
63+
}
64+
cleanups.clear();
65+
66+
// Now the input operands
67+
let inputs = do ia.inputs.map |&(c, in)| {
68+
constraints.push(copy *c);
69+
70+
let inty = ty::arg {
71+
mode: ast::expl(ast::by_copy),
72+
ty: expr_ty(bcx, in)
73+
};
74+
75+
unpack_result!(bcx, {
76+
callee::trans_arg_expr(bcx, inty, in, &mut cleanups, None, callee::DontAutorefArg)
77+
})
78+
79+
};
80+
81+
for cleanups.each |c| {
82+
revoke_clean(bcx, *c);
83+
}
84+
85+
let mut constraints = str::connect(constraints, ",");
86+
87+
let mut clobbers = getClobbers();
88+
if *ia.clobbers != ~"" && clobbers != ~"" {
89+
clobbers = *ia.clobbers + ~"," + clobbers;
90+
} else {
91+
clobbers += *ia.clobbers;
92+
};
93+
94+
// Add the clobbers to our constraints list
95+
if clobbers != ~"" && constraints != ~"" {
96+
constraints += ~"," + clobbers;
97+
} else {
98+
constraints += clobbers;
99+
}
100+
101+
debug!("Asm Constraints: %?", constraints);
102+
103+
let numOutputs = outputs.len();
104+
105+
// Depending on how many outputs we have, the return type is different
106+
let output = if numOutputs == 0 {
107+
T_void()
108+
} else if numOutputs == 1 {
109+
val_ty(outputs[0])
110+
} else {
111+
T_struct(outputs.map(|o| val_ty(*o)))
112+
};
113+
114+
let dialect = match ia.dialect {
115+
ast::asm_att => lib::llvm::AD_ATT,
116+
ast::asm_intel => lib::llvm::AD_Intel
117+
};
118+
119+
let r = do str::as_c_str(*ia.asm) |a| {
120+
do str::as_c_str(constraints) |c| {
121+
InlineAsmCall(bcx, a, c, inputs, output, ia.volatile, ia.alignstack, dialect)
122+
}
123+
};
124+
125+
// Again, based on how many outputs we have
126+
if numOutputs == 1 {
127+
let op = PointerCast(bcx, aoutputs[0], T_ptr(val_ty(outputs[0])));
128+
Store(bcx, r, op);
129+
} else {
130+
for aoutputs.eachi |i, o| {
131+
let v = ExtractValue(bcx, r, i);
132+
let op = PointerCast(bcx, *o, T_ptr(val_ty(outputs[i])));
133+
Store(bcx, v, op);
134+
}
135+
}
136+
137+
return bcx;
138+
139+
}
140+
141+
// Default per-arch clobbers
142+
// Basically what clang does
143+
144+
#[cfg(target_arch = "arm")]
145+
#[cfg(target_arch = "mips")]
146+
fn getClobbers() -> ~str {
147+
~""
148+
}
149+
150+
#[cfg(target_arch = "x86")]
151+
#[cfg(target_arch = "x86_64")]
152+
fn getClobbers() -> ~str {
153+
~"~{dirflag},~{fpsr},~{flags}"
154+
}

Diff for: src/librustc/middle/trans/expr.rs

+3-102
Original file line numberDiff line numberDiff line change
@@ -128,6 +128,7 @@ use metadata::csearch;
128128
use middle::borrowck::root_map_key;
129129
use middle::trans::_match;
130130
use middle::trans::adt;
131+
use middle::trans::asm;
131132
use middle::trans::base;
132133
use middle::trans::base::*;
133134
use middle::trans::build::*;
@@ -548,108 +549,8 @@ fn trans_rvalue_stmt_unadjusted(bcx: block, expr: @ast::expr) -> block {
548549
ast::expr_paren(a) => {
549550
return trans_rvalue_stmt_unadjusted(bcx, a);
550551
}
551-
ast::expr_inline_asm(asm, ref ins, ref outs,
552-
clobs, volatile, alignstack) => {
553-
let mut constraints = ~[];
554-
let mut cleanups = ~[];
555-
let mut aoutputs = ~[];
556-
557-
let outputs = do outs.map |&(c, out)| {
558-
constraints.push(copy *c);
559-
560-
let aoutty = ty::arg {
561-
mode: ast::expl(ast::by_copy),
562-
ty: expr_ty(bcx, out)
563-
};
564-
aoutputs.push(unpack_result!(bcx, {
565-
callee::trans_arg_expr(bcx, aoutty, out, &mut cleanups,
566-
None, callee::DontAutorefArg)
567-
}));
568-
569-
let e = match out.node {
570-
ast::expr_addr_of(_, e) => e,
571-
_ => fail!(~"Expression must be addr of")
572-
};
573-
574-
let outty = ty::arg {
575-
mode: ast::expl(ast::by_copy),
576-
ty: expr_ty(bcx, e)
577-
};
578-
579-
unpack_result!(bcx, {
580-
callee::trans_arg_expr(bcx, outty, e, &mut cleanups,
581-
None, callee::DontAutorefArg)
582-
})
583-
584-
};
585-
586-
for cleanups.each |c| {
587-
revoke_clean(bcx, *c);
588-
}
589-
cleanups = ~[];
590-
591-
let inputs = do ins.map |&(c, in)| {
592-
constraints.push(copy *c);
593-
594-
let inty = ty::arg {
595-
mode: ast::expl(ast::by_copy),
596-
ty: expr_ty(bcx, in)
597-
};
598-
599-
unpack_result!(bcx, {
600-
callee::trans_arg_expr(bcx, inty, in, &mut cleanups,
601-
None, callee::DontAutorefArg)
602-
})
603-
604-
};
605-
606-
for cleanups.each |c| {
607-
revoke_clean(bcx, *c);
608-
}
609-
610-
let mut constraints = str::connect(constraints, ",");
611-
612-
// Add the clobbers
613-
if *clobs != ~"" {
614-
if constraints == ~"" {
615-
constraints += *clobs;
616-
} else {
617-
constraints += ~"," + *clobs;
618-
}
619-
} else {
620-
constraints += *clobs;
621-
}
622-
623-
debug!("Asm Constraints: %?", constraints);
624-
625-
let output = if outputs.len() == 0 {
626-
T_void()
627-
} else if outputs.len() == 1 {
628-
val_ty(outputs[0])
629-
} else {
630-
T_struct(outputs.map(|o| val_ty(*o)))
631-
};
632-
633-
let r = do str::as_c_str(*asm) |a| {
634-
do str::as_c_str(constraints) |c| {
635-
InlineAsmCall(bcx, a, c, inputs, output, volatile,
636-
alignstack, lib::llvm::AD_ATT)
637-
}
638-
};
639-
640-
if outputs.len() == 1 {
641-
let op = PointerCast(bcx, aoutputs[0],
642-
T_ptr(val_ty(outputs[0])));
643-
Store(bcx, r, op);
644-
} else {
645-
for aoutputs.eachi |i, o| {
646-
let v = ExtractValue(bcx, r, i);
647-
let op = PointerCast(bcx, *o, T_ptr(val_ty(outputs[i])));
648-
Store(bcx, v, op);
649-
}
650-
}
651-
652-
return bcx;
552+
ast::expr_inline_asm(ref a) => {
553+
return asm::trans_inline_asm(bcx, a);
653554
}
654555
_ => {
655556
bcx.tcx().sess.span_bug(

Diff for: src/librustc/middle/trans/type_use.rs

+3-3
Original file line numberDiff line numberDiff line change
@@ -360,11 +360,11 @@ pub fn mark_for_expr(cx: Context, e: @expr) {
360360
mark_for_method_call(cx, e.id, e.callee_id);
361361
}
362362

363-
expr_inline_asm(_, ref ins, ref outs, _, _, _) => {
364-
for ins.each |&(_, in)| {
363+
expr_inline_asm(ref ia) => {
364+
for ia.inputs.each |&(_, in)| {
365365
node_type_needs(cx, use_repr, in.id);
366366
}
367-
for outs.each |&(_, out)| {
367+
for ia.outputs.each |&(_, out)| {
368368
node_type_needs(cx, use_repr, out.id);
369369
}
370370
}

Diff for: src/librustc/middle/typeck/check/mod.rs

+3-3
Original file line numberDiff line numberDiff line change
@@ -2336,13 +2336,13 @@ pub fn check_expr_with_unifier(fcx: @mut FnCtxt,
23362336
let region_lb = ty::re_scope(expr.id);
23372337
instantiate_path(fcx, pth, tpt, expr.span, expr.id, region_lb);
23382338
}
2339-
ast::expr_inline_asm(_, ref ins, ref outs, _, _, _) => {
2339+
ast::expr_inline_asm(ref ia) => {
23402340
fcx.require_unsafe(expr.span, ~"use of inline assembly");
23412341

2342-
for ins.each |&(_, in)| {
2342+
for ia.inputs.each |&(_, in)| {
23432343
check_expr(fcx, in);
23442344
}
2345-
for outs.each |&(_, out)| {
2345+
for ia.outputs.each |&(_, out)| {
23462346
check_expr(fcx, out);
23472347
}
23482348
fcx.write_nil(id);

Diff for: src/librustc/rustc.rc

+1
Original file line numberDiff line numberDiff line change
@@ -80,6 +80,7 @@ pub mod middle {
8080
pub mod reachable;
8181
pub mod machine;
8282
pub mod adt;
83+
pub mod asm;
8384
}
8485
pub mod ty;
8586
pub mod resolve;

Diff for: src/libsyntax/ast.rs

+22-4
Original file line numberDiff line numberDiff line change
@@ -593,10 +593,7 @@ pub enum expr_ {
593593
expr_ret(Option<@expr>),
594594
expr_log(@expr, @expr),
595595
596-
expr_inline_asm(@~str, // asm
597-
~[(@~str, @expr)], // inputs
598-
~[(@~str, @expr)], // outputs
599-
@~str, bool, bool), // clobbers, volatile, align stack
596+
expr_inline_asm(inline_asm),
600597
601598
expr_mac(mac),
602599
@@ -930,6 +927,27 @@ impl to_bytes::IterBytes for Ty {
930927
}
931928
}
932929
930+
#[auto_encode]
931+
#[auto_decode]
932+
#[deriving(Eq)]
933+
pub enum asm_dialect {
934+
asm_att,
935+
asm_intel
936+
}
937+
938+
#[auto_encode]
939+
#[auto_decode]
940+
#[deriving(Eq)]
941+
pub struct inline_asm {
942+
asm: @~str,
943+
clobbers: @~str,
944+
inputs: ~[(@~str, @expr)],
945+
outputs: ~[(@~str, @expr)],
946+
volatile: bool,
947+
alignstack: bool,
948+
dialect: asm_dialect
949+
}
950+
933951
#[auto_encode]
934952
#[auto_decode]
935953
#[deriving(Eq)]

0 commit comments

Comments
 (0)