Skip to content

Commit a7f00cb

Browse files
committed
Fix a bug in inline assembly codegen where host clobbers were always used regardless of target
1 parent 883551b commit a7f00cb

File tree

1 file changed

+26
-47
lines changed
  • src/librustc_trans/trans

1 file changed

+26
-47
lines changed

src/librustc_trans/trans/asm.rs

Lines changed: 26 additions & 47 deletions
Original file line numberDiff line numberDiff line change
@@ -76,43 +76,34 @@ pub fn trans_inline_asm<'blk, 'tcx>(bcx: Block<'blk, 'tcx>, ia: &ast::InlineAsm)
7676
// no failure occurred preparing operands, no need to cleanup
7777
fcx.pop_custom_cleanup_scope(temp_scope);
7878

79-
let mut constraints = constraints.iter()
80-
.map(|s| s.to_string())
81-
.chain(ext_constraints.into_iter())
82-
.collect::<Vec<String>>()
83-
.connect(",");
84-
85-
let mut clobbers = ia.clobbers.iter()
86-
.map(|s| format!("~{{{}}}", &s))
87-
.collect::<Vec<String>>()
88-
.connect(",");
89-
let more_clobbers = get_clobbers();
90-
if !more_clobbers.is_empty() {
91-
if !clobbers.is_empty() {
92-
clobbers.push(',');
93-
}
94-
clobbers.push_str(&more_clobbers[..]);
95-
}
96-
97-
// Add the clobbers to our constraints list
98-
if clobbers.len() != 0 && constraints.len() != 0 {
99-
constraints.push(',');
100-
constraints.push_str(&clobbers[..]);
101-
} else {
102-
constraints.push_str(&clobbers[..]);
103-
}
79+
let clobbers = ia.clobbers.iter()
80+
.map(|s| format!("~{{{}}}", &s))
81+
.collect::<Vec<String>>();
82+
83+
// Default per-arch clobbers
84+
// Basically what clang does
85+
let arch_clobbers = match bcx.sess().target.target.arch.as_slice() {
86+
"x86" | "x86_64" => vec!("~{dirflag}", "~{fpsr}", "~{flags}"),
87+
_ => Vec::new()
88+
};
10489

105-
debug!("Asm Constraints: {}", &constraints[..]);
90+
let all_constraints= constraints.iter()
91+
.map(|s| s.to_string())
92+
.chain(ext_constraints.into_iter())
93+
.chain(clobbers.into_iter())
94+
.chain(arch_clobbers.into_iter()
95+
.map(|s| s.to_string()))
96+
.collect::<Vec<String>>()
97+
.connect(",");
10698

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

109101
// Depending on how many outputs we have, the return type is different
110-
let output_type = if num_outputs == 0 {
111-
Type::void(bcx.ccx())
112-
} else if num_outputs == 1 {
113-
output_types[0]
114-
} else {
115-
Type::struct_(bcx.ccx(), &output_types[..], false)
102+
let num_outputs = outputs.len();
103+
let output_type = match num_outputs {
104+
0 => Type::void(bcx.ccx()),
105+
1 => output_types[0],
106+
_ => Type::struct_(bcx.ccx(), &output_types[..], false)
116107
};
117108

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

123114
let asm = CString::new(ia.asm.as_bytes()).unwrap();
124-
let constraints = CString::new(constraints).unwrap();
115+
let constraint_cstr = CString::new(all_constraints).unwrap();
125116
let r = InlineAsmCall(bcx,
126117
asm.as_ptr(),
127-
constraints.as_ptr(),
118+
constraint_cstr.as_ptr(),
128119
&inputs,
129120
output_type,
130121
ia.volatile,
@@ -158,15 +149,3 @@ pub fn trans_inline_asm<'blk, 'tcx>(bcx: Block<'blk, 'tcx>, ia: &ast::InlineAsm)
158149

159150
}
160151

161-
// Default per-arch clobbers
162-
// Basically what clang does
163-
164-
#[cfg(not(any(target_arch = "x86", target_arch = "x86_64")))]
165-
fn get_clobbers() -> String {
166-
"".to_string()
167-
}
168-
169-
#[cfg(any(target_arch = "x86", target_arch = "x86_64"))]
170-
fn get_clobbers() -> String {
171-
"~{dirflag},~{fpsr},~{flags}".to_string()
172-
}

0 commit comments

Comments
 (0)