Skip to content

Commit

Permalink
Fix a bug in inline assembly codegen where host clobbers were always …
Browse files Browse the repository at this point in the history
…used regardless of target
  • Loading branch information
woehr committed Mar 18, 2015
1 parent 883551b commit a7f00cb
Showing 1 changed file with 26 additions and 47 deletions.
73 changes: 26 additions & 47 deletions src/librustc_trans/trans/asm.rs
Expand Up @@ -76,43 +76,34 @@ pub fn trans_inline_asm<'blk, 'tcx>(bcx: Block<'blk, 'tcx>, ia: &ast::InlineAsm)
// no failure occurred preparing operands, no need to cleanup
fcx.pop_custom_cleanup_scope(temp_scope);

let mut constraints = constraints.iter()
.map(|s| s.to_string())
.chain(ext_constraints.into_iter())
.collect::<Vec<String>>()
.connect(",");

let mut clobbers = ia.clobbers.iter()
.map(|s| format!("~{{{}}}", &s))
.collect::<Vec<String>>()
.connect(",");
let more_clobbers = get_clobbers();
if !more_clobbers.is_empty() {
if !clobbers.is_empty() {
clobbers.push(',');
}
clobbers.push_str(&more_clobbers[..]);
}

// Add the clobbers to our constraints list
if clobbers.len() != 0 && constraints.len() != 0 {
constraints.push(',');
constraints.push_str(&clobbers[..]);
} else {
constraints.push_str(&clobbers[..]);
}
let clobbers = ia.clobbers.iter()
.map(|s| format!("~{{{}}}", &s))
.collect::<Vec<String>>();

// Default per-arch clobbers
// Basically what clang does
let arch_clobbers = match bcx.sess().target.target.arch.as_slice() {
"x86" | "x86_64" => vec!("~{dirflag}", "~{fpsr}", "~{flags}"),
_ => Vec::new()
};

debug!("Asm Constraints: {}", &constraints[..]);
let all_constraints= constraints.iter()
.map(|s| s.to_string())
.chain(ext_constraints.into_iter())
.chain(clobbers.into_iter())
.chain(arch_clobbers.into_iter()
.map(|s| s.to_string()))
.collect::<Vec<String>>()
.connect(",");

let num_outputs = outputs.len();
debug!("Asm Constraints: {}", &all_constraints[..]);

// Depending on how many outputs we have, the return type is different
let output_type = if num_outputs == 0 {
Type::void(bcx.ccx())
} else if num_outputs == 1 {
output_types[0]
} else {
Type::struct_(bcx.ccx(), &output_types[..], false)
let num_outputs = outputs.len();
let output_type = match num_outputs {
0 => Type::void(bcx.ccx()),
1 => output_types[0],
_ => Type::struct_(bcx.ccx(), &output_types[..], false)
};

let dialect = match ia.dialect {
Expand All @@ -121,10 +112,10 @@ pub fn trans_inline_asm<'blk, 'tcx>(bcx: Block<'blk, 'tcx>, ia: &ast::InlineAsm)
};

let asm = CString::new(ia.asm.as_bytes()).unwrap();
let constraints = CString::new(constraints).unwrap();
let constraint_cstr = CString::new(all_constraints).unwrap();
let r = InlineAsmCall(bcx,
asm.as_ptr(),
constraints.as_ptr(),
constraint_cstr.as_ptr(),
&inputs,
output_type,
ia.volatile,
Expand Down Expand Up @@ -158,15 +149,3 @@ pub fn trans_inline_asm<'blk, 'tcx>(bcx: Block<'blk, 'tcx>, ia: &ast::InlineAsm)

}

// Default per-arch clobbers
// Basically what clang does

#[cfg(not(any(target_arch = "x86", target_arch = "x86_64")))]
fn get_clobbers() -> String {
"".to_string()
}

#[cfg(any(target_arch = "x86", target_arch = "x86_64"))]
fn get_clobbers() -> String {
"~{dirflag},~{fpsr},~{flags}".to_string()
}

0 comments on commit a7f00cb

Please sign in to comment.