Skeleton for multiple arch support

This commit is contained in:
Gary Guo 2021-11-22 02:56:56 +00:00
parent fe3ba31860
commit eaf88c5b52

View File

@ -402,9 +402,12 @@ fn generate_asm_wrapper(&self, asm_name: &str) -> String {
writeln!(generated_asm, ".section .text.{},\"ax\",@progbits", asm_name).unwrap(); writeln!(generated_asm, ".section .text.{},\"ax\",@progbits", asm_name).unwrap();
writeln!(generated_asm, "{}:", asm_name).unwrap(); writeln!(generated_asm, "{}:", asm_name).unwrap();
let is_x86 = matches!(self.arch, InlineAsmArch::X86 | InlineAsmArch::X86_64);
if is_x86 {
generated_asm.push_str(".intel_syntax noprefix\n"); generated_asm.push_str(".intel_syntax noprefix\n");
generated_asm.push_str(" push rbp\n"); }
generated_asm.push_str(" mov rbp,rdi\n"); Self::prologue(&mut generated_asm, self.arch);
// Save clobbered registers // Save clobbered registers
if !self.options.contains(InlineAsmOptions::NORETURN) { if !self.options.contains(InlineAsmOptions::NORETURN) {
@ -414,7 +417,7 @@ fn generate_asm_wrapper(&self, asm_name: &str) -> String {
.zip(self.stack_slots_clobber.iter().copied()) .zip(self.stack_slots_clobber.iter().copied())
.filter_map(|(r, s)| r.zip(s)) .filter_map(|(r, s)| r.zip(s))
{ {
save_register(&mut generated_asm, self.arch, reg, slot); Self::save_register(&mut generated_asm, self.arch, reg, slot);
} }
} }
@ -425,10 +428,10 @@ fn generate_asm_wrapper(&self, asm_name: &str) -> String {
.zip(self.stack_slots_input.iter().copied()) .zip(self.stack_slots_input.iter().copied())
.filter_map(|(r, s)| r.zip(s)) .filter_map(|(r, s)| r.zip(s))
{ {
restore_register(&mut generated_asm, self.arch, reg, slot); Self::restore_register(&mut generated_asm, self.arch, reg, slot);
} }
if self.options.contains(InlineAsmOptions::ATT_SYNTAX) { if is_x86 && self.options.contains(InlineAsmOptions::ATT_SYNTAX) {
generated_asm.push_str(".att_syntax\n"); generated_asm.push_str(".att_syntax\n");
} }
@ -460,7 +463,7 @@ fn generate_asm_wrapper(&self, asm_name: &str) -> String {
.zip(self.stack_slots_output.iter().copied()) .zip(self.stack_slots_output.iter().copied())
.filter_map(|(r, s)| r.zip(s)) .filter_map(|(r, s)| r.zip(s))
{ {
save_register(&mut generated_asm, self.arch, reg, slot); Self::save_register(&mut generated_asm, self.arch, reg, slot);
} }
// Restore clobbered registers // Restore clobbered registers
@ -470,22 +473,84 @@ fn generate_asm_wrapper(&self, asm_name: &str) -> String {
.zip(self.stack_slots_clobber.iter().copied()) .zip(self.stack_slots_clobber.iter().copied())
.filter_map(|(r, s)| r.zip(s)) .filter_map(|(r, s)| r.zip(s))
{ {
restore_register(&mut generated_asm, self.arch, reg, slot); Self::restore_register(&mut generated_asm, self.arch, reg, slot);
} }
generated_asm.push_str(" pop rbp\n"); Self::epilogue(&mut generated_asm, self.arch);
generated_asm.push_str(" ret\n");
} else { } else {
generated_asm.push_str(" ud2\n"); Self::epilogue_noreturn(&mut generated_asm, self.arch);
} }
if is_x86 {
generated_asm.push_str(".att_syntax\n"); generated_asm.push_str(".att_syntax\n");
}
writeln!(generated_asm, ".size {name}, .-{name}", name = asm_name).unwrap(); writeln!(generated_asm, ".size {name}, .-{name}", name = asm_name).unwrap();
generated_asm.push_str(".text\n"); generated_asm.push_str(".text\n");
generated_asm.push_str("\n\n"); generated_asm.push_str("\n\n");
generated_asm generated_asm
} }
fn prologue(generated_asm: &mut String, arch: InlineAsmArch) {
match arch {
InlineAsmArch::X86_64 => {
generated_asm.push_str(" push rbp\n");
generated_asm.push_str(" mov rbp,rdi\n");
}
_ => unimplemented!("prologue for {:?}", arch),
}
}
fn epilogue(generated_asm: &mut String, arch: InlineAsmArch) {
match arch {
InlineAsmArch::X86_64 => {
generated_asm.push_str(" pop rbp\n");
generated_asm.push_str(" ret\n");
}
_ => unimplemented!("epilogue for {:?}", arch),
}
}
fn epilogue_noreturn(generated_asm: &mut String, arch: InlineAsmArch) {
match arch {
InlineAsmArch::X86_64 => {
generated_asm.push_str(" ud2\n");
}
_ => unimplemented!("epilogue_noreturn for {:?}", arch),
}
}
fn save_register(
generated_asm: &mut String,
arch: InlineAsmArch,
reg: InlineAsmReg,
offset: Size,
) {
match arch {
InlineAsmArch::X86_64 => {
write!(generated_asm, " mov [rbp+0x{:x}], ", offset.bytes()).unwrap();
reg.emit(generated_asm, InlineAsmArch::X86_64, None).unwrap();
generated_asm.push('\n');
}
_ => unimplemented!("save_register for {:?}", arch),
}
}
fn restore_register(
generated_asm: &mut String,
arch: InlineAsmArch,
reg: InlineAsmReg,
offset: Size,
) {
match arch {
InlineAsmArch::X86_64 => {
generated_asm.push_str(" mov ");
reg.emit(generated_asm, InlineAsmArch::X86_64, None).unwrap();
writeln!(generated_asm, ", [rbp+0x{:x}]", offset.bytes()).unwrap();
}
_ => unimplemented!("restore_register for {:?}", arch),
}
}
} }
fn call_inline_asm<'tcx>( fn call_inline_asm<'tcx>(
@ -533,30 +598,3 @@ fn call_inline_asm<'tcx>(
place.write_cvalue(fx, CValue::by_val(value, place.layout())); place.write_cvalue(fx, CValue::by_val(value, place.layout()));
} }
} }
fn save_register(generated_asm: &mut String, arch: InlineAsmArch, reg: InlineAsmReg, offset: Size) {
match arch {
InlineAsmArch::X86_64 => {
write!(generated_asm, " mov [rbp+0x{:x}], ", offset.bytes()).unwrap();
reg.emit(generated_asm, InlineAsmArch::X86_64, None).unwrap();
generated_asm.push('\n');
}
_ => unimplemented!("save_register for {:?}", arch),
}
}
fn restore_register(
generated_asm: &mut String,
arch: InlineAsmArch,
reg: InlineAsmReg,
offset: Size,
) {
match arch {
InlineAsmArch::X86_64 => {
generated_asm.push_str(" mov ");
reg.emit(generated_asm, InlineAsmArch::X86_64, None).unwrap();
writeln!(generated_asm, ", [rbp+0x{:x}]", offset.bytes()).unwrap();
}
_ => unimplemented!("restore_register for {:?}", arch),
}
}