libsyntax: use a struct for inline asm in ast.

This commit is contained in:
Luqman Aden 2013-03-27 13:42:21 -07:00
parent 727a565f1e
commit 203d691a6b
10 changed files with 68 additions and 49 deletions

View file

@ -1346,11 +1346,11 @@ pub impl Liveness {
self.propagate_through_expr(e, succ)
}
expr_inline_asm(_, ref ins, ref outs, _, _, _) =>{
let succ = do ins.foldr(succ) |&(_, expr), succ| {
expr_inline_asm(ref ia) =>{
let succ = do ia.inputs.foldr(succ) |&(_, expr), succ| {
self.propagate_through_expr(expr, succ)
};
do outs.foldr(succ) |&(_, expr), succ| {
do ia.outputs.foldr(succ) |&(_, expr), succ| {
self.propagate_through_expr(expr, succ)
}
}
@ -1620,14 +1620,19 @@ fn check_expr(expr: @expr, &&self: @Liveness, vt: vt<@Liveness>) {
visit::visit_expr(expr, self, vt);
}
expr_inline_asm(_, ref ins, ref outs, _, _, _) => {
for ins.each |&(_, in)| {
expr_inline_asm(ref ia) => {
for ia.inputs.each |&(_, in)| {
(vt.visit_expr)(in, self, vt);
}
// Output operands must be lvalues
for outs.each |&(_, out)| {
self.check_lvalue(out, vt);
for ia.outputs.each |&(_, out)| {
match out.node {
expr_addr_of(_, inner) => {
self.check_lvalue(inner, vt);
}
_ => {}
}
(vt.visit_expr)(out, self, vt);
}

View file

@ -21,11 +21,9 @@ use middle::trans::common::*;
use middle::ty;
use syntax::ast;
use syntax::ast::*;
// Take an inline assembly expression and splat it out via LLVM
pub fn trans_inline_asm(bcx: block, asm: @~str, ins: &[(@~str, @expr)], outs: &[(@~str, @expr)],
clobs: @~str, volatile: bool, alignstack: bool) -> block {
pub fn trans_inline_asm(bcx: block, ia: &ast::inline_asm) -> block {
let mut bcx = bcx;
let mut constraints = ~[];
@ -33,7 +31,7 @@ pub fn trans_inline_asm(bcx: block, asm: @~str, ins: &[(@~str, @expr)], outs: &[
let mut aoutputs = ~[];
// Prepare the output operands
let outputs = do outs.map |&(c, out)| {
let outputs = do ia.outputs.map |&(c, out)| {
constraints.push(copy *c);
let aoutty = ty::arg {
@ -66,7 +64,7 @@ pub fn trans_inline_asm(bcx: block, asm: @~str, ins: &[(@~str, @expr)], outs: &[
cleanups.clear();
// Now the input operands
let inputs = do ins.map |&(c, in)| {
let inputs = do ia.inputs.map |&(c, in)| {
constraints.push(copy *c);
let inty = ty::arg {
@ -87,10 +85,10 @@ pub fn trans_inline_asm(bcx: block, asm: @~str, ins: &[(@~str, @expr)], outs: &[
let mut constraints = str::connect(constraints, ",");
// Add the clobbers to our constraints list
if *clobs != ~"" && constraints != ~"" {
constraints += ~"," + *clobs;
if *ia.clobbers != ~"" && constraints != ~"" {
constraints += ~"," + *ia.clobbers;
} else {
constraints += *clobs;
constraints += *ia.clobbers;
}
debug!("Asm Constraints: %?", constraints);
@ -106,10 +104,10 @@ pub fn trans_inline_asm(bcx: block, asm: @~str, ins: &[(@~str, @expr)], outs: &[
T_struct(outputs.map(|o| val_ty(*o)))
};
let r = do str::as_c_str(*asm) |a| {
let r = do str::as_c_str(*ia.asm) |a| {
do str::as_c_str(constraints) |c| {
// XXX: Allow selection of at&t or intel
InlineAsmCall(bcx, a, c, inputs, output, volatile, alignstack, lib::llvm::AD_ATT)
InlineAsmCall(bcx, a, c, inputs, output, ia.volatile, ia.alignstack, lib::llvm::AD_ATT)
}
};

View file

@ -558,9 +558,8 @@ fn trans_rvalue_stmt_unadjusted(bcx: block, expr: @ast::expr) -> block {
ast::expr_paren(a) => {
return trans_rvalue_stmt_unadjusted(bcx, a);
}
ast::expr_inline_asm(asm, ref ins, ref outs,
clobs, volatile, alignstack) => {
return asm::trans_inline_asm(bcx, asm, *ins, *outs, clobs, volatile, alignstack);
ast::expr_inline_asm(ref a) => {
return asm::trans_inline_asm(bcx, a);
}
_ => {
bcx.tcx().sess.span_bug(

View file

@ -360,11 +360,11 @@ pub fn mark_for_expr(cx: Context, e: @expr) {
mark_for_method_call(cx, e.id, e.callee_id);
}
expr_inline_asm(_, ref ins, ref outs, _, _, _) => {
for ins.each |&(_, in)| {
expr_inline_asm(ref ia) => {
for ia.inputs.each |&(_, in)| {
node_type_needs(cx, use_repr, in.id);
}
for outs.each |&(_, out)| {
for ia.outputs.each |&(_, out)| {
node_type_needs(cx, use_repr, out.id);
}
}

View file

@ -2332,13 +2332,13 @@ pub fn check_expr_with_unifier(fcx: @mut FnCtxt,
let region_lb = ty::re_scope(expr.id);
instantiate_path(fcx, pth, tpt, expr.span, expr.id, region_lb);
}
ast::expr_inline_asm(_, ref ins, ref outs, _, _, _) => {
ast::expr_inline_asm(ref ia) => {
fcx.require_unsafe(expr.span, ~"use of inline assembly");
for ins.each |&(_, in)| {
for ia.inputs.each |&(_, in)| {
check_expr(fcx, in);
}
for outs.each |&(_, out)| {
for ia.outputs.each |&(_, out)| {
check_expr(fcx, out);
}
fcx.write_nil(id);

View file

@ -600,10 +600,7 @@ pub enum expr_ {
expr_ret(Option<@expr>),
expr_log(log_level, @expr, @expr),
expr_inline_asm(@~str, // asm
~[(@~str, @expr)], // inputs
~[(@~str, @expr)], // outputs
@~str, bool, bool), // clobbers, volatile, align stack
expr_inline_asm(inline_asm),
expr_mac(mac),
@ -937,6 +934,18 @@ impl to_bytes::IterBytes for Ty {
}
}
#[auto_encode]
#[auto_decode]
#[deriving(Eq)]
pub struct inline_asm {
asm: @~str,
clobbers: @~str,
inputs: ~[(@~str, @expr)],
outputs: ~[(@~str, @expr)],
volatile: bool,
alignstack: bool
}
#[auto_encode]
#[auto_decode]
#[deriving(Eq)]

View file

@ -59,7 +59,7 @@ pub fn expand_asm(cx: @ext_ctxt, sp: span, tts: &[ast::token_tree])
match state {
Asm => {
asm = expr_to_str(cx, p.parse_expr(),
~"inline assembly must be a string literal.");
~"inline assembly must be a string literal.");
}
Outputs => {
while *p.token != token::EOF &&
@ -163,8 +163,14 @@ pub fn expand_asm(cx: @ext_ctxt, sp: span, tts: &[ast::token_tree])
MRExpr(@ast::expr {
id: cx.next_id(),
callee_id: cx.next_id(),
node: ast::expr_inline_asm(@asm, inputs, outputs,
@cons, volatile, alignstack),
node: ast::expr_inline_asm(ast::inline_asm {
asm: @asm,
clobbers: @cons,
inputs: inputs,
outputs: outputs,
volatile: volatile,
alignstack: alignstack
}),
span: sp
})
}

View file

@ -559,13 +559,15 @@ pub fn noop_fold_expr(e: &expr_, fld: @ast_fold) -> expr_ {
fld.fold_expr(e)
)
}
expr_inline_asm(asm, ins, outs, c, v, a) => {
expr_inline_asm(
asm,
ins.map(|&(c, in)| (c, fld.fold_expr(in))),
outs.map(|&(c, out)| (c, fld.fold_expr(out))),
c, v, a
)
expr_inline_asm(a) => {
expr_inline_asm(inline_asm {
asm: a.asm,
clobbers: a.clobbers,
inputs: a.inputs.map(|&(c, in)| (c, fld.fold_expr(in))),
outputs: a.outputs.map(|&(c, out)| (c, fld.fold_expr(out))),
volatile: a.volatile,
alignstack: a.alignstack
})
}
expr_mac(ref mac) => expr_mac(fold_mac((*mac))),
expr_struct(path, ref fields, maybe_expr) => {

View file

@ -1406,16 +1406,16 @@ pub fn print_expr(s: @ps, &&expr: @ast::expr) {
}
}
}
ast::expr_inline_asm(a, in, out, c, v, _) => {
if v {
ast::expr_inline_asm(a) => {
if a.volatile {
word(s.s, ~"__volatile__ asm!");
} else {
word(s.s, ~"asm!");
}
popen(s);
print_string(s, *a);
print_string(s, *a.asm);
word_space(s, ~":");
for out.each |&(co, o)| {
for a.outputs.each |&(co, o)| {
print_string(s, *co);
popen(s);
print_expr(s, o);
@ -1423,7 +1423,7 @@ pub fn print_expr(s: @ps, &&expr: @ast::expr) {
word_space(s, ~",");
}
word_space(s, ~":");
for in.each |&(co, o)| {
for a.inputs.each |&(co, o)| {
print_string(s, *co);
popen(s);
print_expr(s, o);
@ -1431,7 +1431,7 @@ pub fn print_expr(s: @ps, &&expr: @ast::expr) {
word_space(s, ~",");
}
word_space(s, ~":");
print_string(s, *c);
print_string(s, *a.clobbers);
pclose(s);
}
ast::expr_mac(ref m) => print_mac(s, (*m)),

View file

@ -565,11 +565,11 @@ pub fn visit_expr<E>(ex: @expr, e: E, v: vt<E>) {
}
expr_mac(ref mac) => visit_mac((*mac), e, v),
expr_paren(x) => (v.visit_expr)(x, e, v),
expr_inline_asm(_, ins, outs, _, _, _) => {
for ins.each |&(_, in)| {
expr_inline_asm(ref a) => {
for a.inputs.each |&(_, in)| {
(v.visit_expr)(in, e, v);
}
for outs.each |&(_, out)| {
for a.outputs.each |&(_, out)| {
(v.visit_expr)(out, e, v);
}
}