Fix a bug in inline assembly codegen where host clobbers were always used regardless of target

This commit is contained in:
Jordan Woehr 2015-03-17 23:23:13 -06:00
parent 883551b1d7
commit a7f00cbc0c

View file

@ -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 // no failure occurred preparing operands, no need to cleanup
fcx.pop_custom_cleanup_scope(temp_scope); fcx.pop_custom_cleanup_scope(temp_scope);
let mut constraints = constraints.iter() let clobbers = ia.clobbers.iter()
.map(|s| s.to_string()) .map(|s| format!("~{{{}}}", &s))
.chain(ext_constraints.into_iter()) .collect::<Vec<String>>();
.collect::<Vec<String>>()
.connect(",");
let mut clobbers = ia.clobbers.iter() // Default per-arch clobbers
.map(|s| format!("~{{{}}}", &s)) // Basically what clang does
.collect::<Vec<String>>() let arch_clobbers = match bcx.sess().target.target.arch.as_slice() {
.connect(","); "x86" | "x86_64" => vec!("~{dirflag}", "~{fpsr}", "~{flags}"),
let more_clobbers = get_clobbers(); _ => Vec::new()
if !more_clobbers.is_empty() { };
if !clobbers.is_empty() {
clobbers.push(',');
}
clobbers.push_str(&more_clobbers[..]);
}
// Add the clobbers to our constraints list let all_constraints= constraints.iter()
if clobbers.len() != 0 && constraints.len() != 0 { .map(|s| s.to_string())
constraints.push(','); .chain(ext_constraints.into_iter())
constraints.push_str(&clobbers[..]); .chain(clobbers.into_iter())
} else { .chain(arch_clobbers.into_iter()
constraints.push_str(&clobbers[..]); .map(|s| s.to_string()))
} .collect::<Vec<String>>()
.connect(",");
debug!("Asm Constraints: {}", &constraints[..]); debug!("Asm Constraints: {}", &all_constraints[..]);
let num_outputs = outputs.len();
// Depending on how many outputs we have, the return type is different // Depending on how many outputs we have, the return type is different
let output_type = if num_outputs == 0 { let num_outputs = outputs.len();
Type::void(bcx.ccx()) let output_type = match num_outputs {
} else if num_outputs == 1 { 0 => Type::void(bcx.ccx()),
output_types[0] 1 => output_types[0],
} else { _ => Type::struct_(bcx.ccx(), &output_types[..], false)
Type::struct_(bcx.ccx(), &output_types[..], false)
}; };
let dialect = match ia.dialect { let dialect = match ia.dialect {
@ -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 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, let r = InlineAsmCall(bcx,
asm.as_ptr(), asm.as_ptr(),
constraints.as_ptr(), constraint_cstr.as_ptr(),
&inputs, &inputs,
output_type, output_type,
ia.volatile, ia.volatile,
@ -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()
}