Skip to content

Commit e825497

Browse files
authored
Merge pull request #1396 from bjorn3/aarch64_asm
Support inline asm on AArch64
2 parents f1ede97 + 4577c1d commit e825497

File tree

3 files changed

+51
-70
lines changed

3 files changed

+51
-70
lines changed

example/mini_core.rs

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -683,6 +683,12 @@ pub macro cfg() {
683683
/* compiler built-in */
684684
}
685685

686+
#[rustc_builtin_macro]
687+
#[rustc_macro_transparency = "semitransparent"]
688+
pub macro asm() {
689+
/* compiler built-in */
690+
}
691+
686692
#[rustc_builtin_macro]
687693
#[rustc_macro_transparency = "semitransparent"]
688694
pub macro global_asm() {

src/global_asm.rs

Lines changed: 17 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -9,16 +9,22 @@ use std::sync::Arc;
99
use rustc_ast::{InlineAsmOptions, InlineAsmTemplatePiece};
1010
use rustc_hir::{InlineAsmOperand, ItemId};
1111
use rustc_session::config::{OutputFilenames, OutputType};
12+
use rustc_target::asm::InlineAsmArch;
1213

1314
use crate::prelude::*;
1415

1516
pub(crate) fn codegen_global_asm_item(tcx: TyCtxt<'_>, global_asm: &mut String, item_id: ItemId) {
1617
let item = tcx.hir().item(item_id);
1718
if let rustc_hir::ItemKind::GlobalAsm(asm) = item.kind {
18-
if !asm.options.contains(InlineAsmOptions::ATT_SYNTAX) {
19-
global_asm.push_str("\n.intel_syntax noprefix\n");
20-
} else {
21-
global_asm.push_str("\n.att_syntax\n");
19+
let is_x86 =
20+
matches!(tcx.sess.asm_arch.unwrap(), InlineAsmArch::X86 | InlineAsmArch::X86_64);
21+
22+
if is_x86 {
23+
if !asm.options.contains(InlineAsmOptions::ATT_SYNTAX) {
24+
global_asm.push_str("\n.intel_syntax noprefix\n");
25+
} else {
26+
global_asm.push_str("\n.att_syntax\n");
27+
}
2228
}
2329
for piece in asm.template {
2430
match *piece {
@@ -65,7 +71,11 @@ pub(crate) fn codegen_global_asm_item(tcx: TyCtxt<'_>, global_asm: &mut String,
6571
}
6672
}
6773
}
68-
global_asm.push_str("\n.att_syntax\n\n");
74+
75+
global_asm.push('\n');
76+
if is_x86 {
77+
global_asm.push_str(".att_syntax\n\n");
78+
}
6979
} else {
7080
bug!("Expected GlobalAsm found {:?}", item);
7181
}
@@ -115,11 +125,12 @@ pub(crate) fn compile_global_asm(
115125
}
116126

117127
// Remove all LLVM style comments
118-
let global_asm = global_asm
128+
let mut global_asm = global_asm
119129
.lines()
120130
.map(|line| if let Some(index) = line.find("//") { &line[0..index] } else { line })
121131
.collect::<Vec<_>>()
122132
.join("\n");
133+
global_asm.push('\n');
123134

124135
let output_object_file = config.output_filenames.temp_path(OutputType::Object, Some(cgu_name));
125136

src/inline_asm.rs

Lines changed: 28 additions & 64 deletions
Original file line numberDiff line numberDiff line change
@@ -699,50 +699,34 @@ impl<'tcx> InlineAssemblyGenerator<'_, 'tcx> {
699699

700700
fn prologue(generated_asm: &mut String, arch: InlineAsmArch) {
701701
match arch {
702-
InlineAsmArch::X86 => {
703-
generated_asm.push_str(" push ebp\n");
704-
generated_asm.push_str(" mov ebp,[esp+8]\n");
705-
}
706702
InlineAsmArch::X86_64 => {
707703
generated_asm.push_str(" push rbp\n");
708-
generated_asm.push_str(" mov rbp,rdi\n");
709-
}
710-
InlineAsmArch::RiscV32 => {
711-
generated_asm.push_str(" addi sp, sp, -8\n");
712-
generated_asm.push_str(" sw ra, 4(sp)\n");
713-
generated_asm.push_str(" sw s0, 0(sp)\n");
714-
generated_asm.push_str(" mv s0, a0\n");
715-
}
716-
InlineAsmArch::RiscV64 => {
717-
generated_asm.push_str(" addi sp, sp, -16\n");
718-
generated_asm.push_str(" sd ra, 8(sp)\n");
719-
generated_asm.push_str(" sd s0, 0(sp)\n");
720-
generated_asm.push_str(" mv s0, a0\n");
704+
generated_asm.push_str(" mov rbp,rsp\n");
705+
generated_asm.push_str(" push rbx\n"); // rbx is callee saved
706+
// rbx is reserved by LLVM for the "base pointer", so rustc doesn't allow using it
707+
generated_asm.push_str(" mov rbx,rdi\n");
708+
}
709+
InlineAsmArch::AArch64 => {
710+
generated_asm.push_str(" stp fp, lr, [sp, #-32]!\n");
711+
generated_asm.push_str(" mov fp, sp\n");
712+
generated_asm.push_str(" str x19, [sp, #24]\n"); // x19 is callee saved
713+
// x19 is reserved by LLVM for the "base pointer", so rustc doesn't allow using it
714+
generated_asm.push_str(" mov x19, x0\n");
721715
}
722716
_ => unimplemented!("prologue for {:?}", arch),
723717
}
724718
}
725719

726720
fn epilogue(generated_asm: &mut String, arch: InlineAsmArch) {
727721
match arch {
728-
InlineAsmArch::X86 => {
729-
generated_asm.push_str(" pop ebp\n");
730-
generated_asm.push_str(" ret\n");
731-
}
732722
InlineAsmArch::X86_64 => {
723+
generated_asm.push_str(" pop rbx\n");
733724
generated_asm.push_str(" pop rbp\n");
734725
generated_asm.push_str(" ret\n");
735726
}
736-
InlineAsmArch::RiscV32 => {
737-
generated_asm.push_str(" lw s0, 0(sp)\n");
738-
generated_asm.push_str(" lw ra, 4(sp)\n");
739-
generated_asm.push_str(" addi sp, sp, 8\n");
740-
generated_asm.push_str(" ret\n");
741-
}
742-
InlineAsmArch::RiscV64 => {
743-
generated_asm.push_str(" ld s0, 0(sp)\n");
744-
generated_asm.push_str(" ld ra, 8(sp)\n");
745-
generated_asm.push_str(" addi sp, sp, 16\n");
727+
InlineAsmArch::AArch64 => {
728+
generated_asm.push_str(" ldr x19, [sp, #24]\n");
729+
generated_asm.push_str(" ldp fp, lr, [sp], #32\n");
746730
generated_asm.push_str(" ret\n");
747731
}
748732
_ => unimplemented!("epilogue for {:?}", arch),
@@ -751,11 +735,11 @@ impl<'tcx> InlineAssemblyGenerator<'_, 'tcx> {
751735

752736
fn epilogue_noreturn(generated_asm: &mut String, arch: InlineAsmArch) {
753737
match arch {
754-
InlineAsmArch::X86 | InlineAsmArch::X86_64 => {
738+
InlineAsmArch::X86_64 => {
755739
generated_asm.push_str(" ud2\n");
756740
}
757-
InlineAsmArch::RiscV32 | InlineAsmArch::RiscV64 => {
758-
generated_asm.push_str(" ebreak\n");
741+
InlineAsmArch::AArch64 => {
742+
generated_asm.push_str(" brk #0x1");
759743
}
760744
_ => unimplemented!("epilogue_noreturn for {:?}", arch),
761745
}
@@ -768,25 +752,15 @@ impl<'tcx> InlineAssemblyGenerator<'_, 'tcx> {
768752
offset: Size,
769753
) {
770754
match arch {
771-
InlineAsmArch::X86 => {
772-
write!(generated_asm, " mov [ebp+0x{:x}], ", offset.bytes()).unwrap();
773-
reg.emit(generated_asm, InlineAsmArch::X86, None).unwrap();
774-
generated_asm.push('\n');
775-
}
776755
InlineAsmArch::X86_64 => {
777-
write!(generated_asm, " mov [rbp+0x{:x}], ", offset.bytes()).unwrap();
756+
write!(generated_asm, " mov [rbx+0x{:x}], ", offset.bytes()).unwrap();
778757
reg.emit(generated_asm, InlineAsmArch::X86_64, None).unwrap();
779758
generated_asm.push('\n');
780759
}
781-
InlineAsmArch::RiscV32 => {
782-
generated_asm.push_str(" sw ");
783-
reg.emit(generated_asm, InlineAsmArch::RiscV32, None).unwrap();
784-
writeln!(generated_asm, ", 0x{:x}(s0)", offset.bytes()).unwrap();
785-
}
786-
InlineAsmArch::RiscV64 => {
787-
generated_asm.push_str(" sd ");
788-
reg.emit(generated_asm, InlineAsmArch::RiscV64, None).unwrap();
789-
writeln!(generated_asm, ", 0x{:x}(s0)", offset.bytes()).unwrap();
760+
InlineAsmArch::AArch64 => {
761+
generated_asm.push_str(" str ");
762+
reg.emit(generated_asm, InlineAsmArch::AArch64, None).unwrap();
763+
writeln!(generated_asm, ", [x19, 0x{:x}]", offset.bytes()).unwrap();
790764
}
791765
_ => unimplemented!("save_register for {:?}", arch),
792766
}
@@ -799,25 +773,15 @@ impl<'tcx> InlineAssemblyGenerator<'_, 'tcx> {
799773
offset: Size,
800774
) {
801775
match arch {
802-
InlineAsmArch::X86 => {
803-
generated_asm.push_str(" mov ");
804-
reg.emit(generated_asm, InlineAsmArch::X86, None).unwrap();
805-
writeln!(generated_asm, ", [ebp+0x{:x}]", offset.bytes()).unwrap();
806-
}
807776
InlineAsmArch::X86_64 => {
808777
generated_asm.push_str(" mov ");
809778
reg.emit(generated_asm, InlineAsmArch::X86_64, None).unwrap();
810-
writeln!(generated_asm, ", [rbp+0x{:x}]", offset.bytes()).unwrap();
811-
}
812-
InlineAsmArch::RiscV32 => {
813-
generated_asm.push_str(" lw ");
814-
reg.emit(generated_asm, InlineAsmArch::RiscV32, None).unwrap();
815-
writeln!(generated_asm, ", 0x{:x}(s0)", offset.bytes()).unwrap();
779+
writeln!(generated_asm, ", [rbx+0x{:x}]", offset.bytes()).unwrap();
816780
}
817-
InlineAsmArch::RiscV64 => {
818-
generated_asm.push_str(" ld ");
819-
reg.emit(generated_asm, InlineAsmArch::RiscV64, None).unwrap();
820-
writeln!(generated_asm, ", 0x{:x}(s0)", offset.bytes()).unwrap();
781+
InlineAsmArch::AArch64 => {
782+
generated_asm.push_str(" ldr ");
783+
reg.emit(generated_asm, InlineAsmArch::AArch64, None).unwrap();
784+
writeln!(generated_asm, ", [x19, 0x{:x}]", offset.bytes()).unwrap();
821785
}
822786
_ => unimplemented!("restore_register for {:?}", arch),
823787
}

0 commit comments

Comments
 (0)