Skip to content
This repository was archived by the owner on May 28, 2025. It is now read-only.

Commit abed45f

Browse files
committed
Implement asm! codegen
1 parent 342a64c commit abed45f

File tree

8 files changed

+608
-17
lines changed

8 files changed

+608
-17
lines changed

src/librustc_codegen_llvm/asm.rs

Lines changed: 463 additions & 15 deletions
Large diffs are not rendered by default.

src/librustc_codegen_llvm/llvm/ffi.rs

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -124,6 +124,8 @@ pub enum Attribute {
124124
NonLazyBind = 23,
125125
OptimizeNone = 24,
126126
ReturnsTwice = 25,
127+
ReadNone = 26,
128+
InaccessibleMemOnly = 27,
127129
}
128130

129131
/// LLVMIntPredicate

src/librustc_codegen_ssa/mir/analyze.rs

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -358,7 +358,8 @@ pub fn cleanup_kinds(mir: &mir::Body<'_>) -> IndexVec<mir::BasicBlock, CleanupKi
358358
| TerminatorKind::SwitchInt { .. }
359359
| TerminatorKind::Yield { .. }
360360
| TerminatorKind::FalseEdges { .. }
361-
| TerminatorKind::FalseUnwind { .. } => { /* nothing to do */ }
361+
| TerminatorKind::FalseUnwind { .. }
362+
| TerminatorKind::InlineAsm { .. } => { /* nothing to do */ }
362363
TerminatorKind::Call { cleanup: unwind, .. }
363364
| TerminatorKind::Assert { cleanup: unwind, .. }
364365
| TerminatorKind::DropAndReplace { unwind, .. }

src/librustc_codegen_ssa/mir/block.rs

Lines changed: 93 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@ use crate::meth;
99
use crate::traits::*;
1010
use crate::MemFlags;
1111

12+
use rustc_ast::ast;
1213
use rustc_hir::lang_items;
1314
use rustc_index::vec::Idx;
1415
use rustc_middle::mir;
@@ -914,6 +915,98 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> {
914915
mir::TerminatorKind::FalseEdges { .. } | mir::TerminatorKind::FalseUnwind { .. } => {
915916
bug!("borrowck false edges in codegen")
916917
}
918+
919+
mir::TerminatorKind::InlineAsm { template, ref operands, options, ref destination } => {
920+
let span = terminator.source_info.span;
921+
922+
let operands: Vec<_> = operands
923+
.iter()
924+
.map(|op| match *op {
925+
mir::InlineAsmOperand::In { reg, ref value } => {
926+
let value = self.codegen_operand(&mut bx, value);
927+
InlineAsmOperandRef::In { reg, value }
928+
}
929+
mir::InlineAsmOperand::Out { reg, late, ref place } => {
930+
let place =
931+
place.map(|place| self.codegen_place(&mut bx, place.as_ref()));
932+
InlineAsmOperandRef::Out { reg, late, place }
933+
}
934+
mir::InlineAsmOperand::InOut { reg, late, ref in_value, ref out_place } => {
935+
let in_value = self.codegen_operand(&mut bx, in_value);
936+
let out_place = out_place
937+
.map(|out_place| self.codegen_place(&mut bx, out_place.as_ref()));
938+
InlineAsmOperandRef::InOut { reg, late, in_value, out_place }
939+
}
940+
mir::InlineAsmOperand::Const { ref value } => {
941+
if let mir::Operand::Constant(constant) = value {
942+
let const_value =
943+
self.eval_mir_constant(constant).unwrap_or_else(|_| {
944+
span_bug!(span, "asm const cannot be resolved")
945+
});
946+
let ty = constant.literal.ty;
947+
let value = const_value
948+
.try_to_bits_for_ty(bx.tcx(), ty::ParamEnv::reveal_all(), ty)
949+
.unwrap_or_else(|| {
950+
span_bug!(span, "asm const has non-scalar value")
951+
});
952+
let string = match ty.kind {
953+
ty::Uint(_) => value.to_string(),
954+
ty::Int(int_ty) => {
955+
match int_ty.normalize(bx.tcx().sess.target.ptr_width) {
956+
ast::IntTy::I8 => (value as i8).to_string(),
957+
ast::IntTy::I16 => (value as i16).to_string(),
958+
ast::IntTy::I32 => (value as i32).to_string(),
959+
ast::IntTy::I64 => (value as i64).to_string(),
960+
ast::IntTy::I128 => (value as i128).to_string(),
961+
ast::IntTy::Isize => unreachable!(),
962+
}
963+
}
964+
ty::Float(ast::FloatTy::F32) => {
965+
f32::from_bits(value as u32).to_string()
966+
}
967+
ty::Float(ast::FloatTy::F64) => {
968+
f64::from_bits(value as u64).to_string()
969+
}
970+
_ => span_bug!(span, "asm const has bad type {}", ty),
971+
};
972+
InlineAsmOperandRef::Const { string }
973+
} else {
974+
span_bug!(span, "asm const is not a constant");
975+
}
976+
}
977+
mir::InlineAsmOperand::SymFn { ref value } => {
978+
if let ty::FnDef(def_id, substs) = value.literal.ty.kind {
979+
let instance = ty::Instance::resolve(
980+
bx.tcx(),
981+
ty::ParamEnv::reveal_all(),
982+
def_id,
983+
substs,
984+
)
985+
.unwrap()
986+
.unwrap();
987+
InlineAsmOperandRef::SymFn { instance }
988+
} else {
989+
span_bug!(span, "invalid type for asm sym (fn)");
990+
}
991+
}
992+
mir::InlineAsmOperand::SymStatic { ref value } => {
993+
if let Some(def_id) = value.check_static_ptr(bx.tcx()) {
994+
InlineAsmOperandRef::SymStatic { def_id }
995+
} else {
996+
span_bug!(span, "invalid type for asm sym (static)");
997+
}
998+
}
999+
})
1000+
.collect();
1001+
1002+
bx.codegen_inline_asm(template, &operands, options, span);
1003+
1004+
if let Some(target) = destination {
1005+
helper.funclet_br(self, &mut bx, *target);
1006+
} else {
1007+
bx.unreachable();
1008+
}
1009+
}
9171010
}
9181011
}
9191012

src/librustc_codegen_ssa/traits/asm.rs

Lines changed: 41 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,39 @@
11
use super::BackendTypes;
2+
use crate::mir::operand::OperandRef;
23
use crate::mir::place::PlaceRef;
4+
use rustc_hir::def_id::DefId;
35
use rustc_hir::{GlobalAsm, LlvmInlineAsmInner};
6+
use rustc_middle::ty::Instance;
47
use rustc_span::Span;
8+
use rustc_target::asm::{InlineAsmOptions, InlineAsmRegOrRegClass, InlineAsmTemplatePiece};
9+
10+
#[derive(Debug)]
11+
pub enum InlineAsmOperandRef<'tcx, B: BackendTypes + ?Sized> {
12+
In {
13+
reg: InlineAsmRegOrRegClass,
14+
value: OperandRef<'tcx, B::Value>,
15+
},
16+
Out {
17+
reg: InlineAsmRegOrRegClass,
18+
late: bool,
19+
place: Option<PlaceRef<'tcx, B::Value>>,
20+
},
21+
InOut {
22+
reg: InlineAsmRegOrRegClass,
23+
late: bool,
24+
in_value: OperandRef<'tcx, B::Value>,
25+
out_place: Option<PlaceRef<'tcx, B::Value>>,
26+
},
27+
Const {
28+
string: String,
29+
},
30+
SymFn {
31+
instance: Instance<'tcx>,
32+
},
33+
SymStatic {
34+
def_id: DefId,
35+
},
36+
}
537

638
pub trait AsmBuilderMethods<'tcx>: BackendTypes {
739
/// Take an inline assembly expression and splat it out via LLVM
@@ -12,6 +44,15 @@ pub trait AsmBuilderMethods<'tcx>: BackendTypes {
1244
inputs: Vec<Self::Value>,
1345
span: Span,
1446
) -> bool;
47+
48+
/// Take an inline assembly expression and splat it out via LLVM
49+
fn codegen_inline_asm(
50+
&mut self,
51+
template: &[InlineAsmTemplatePiece],
52+
operands: &[InlineAsmOperandRef<'tcx, Self>],
53+
options: InlineAsmOptions,
54+
span: Span,
55+
);
1556
}
1657

1758
pub trait AsmMethods {

src/librustc_codegen_ssa/traits/mod.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -28,7 +28,7 @@ mod type_;
2828
mod write;
2929

3030
pub use self::abi::AbiBuilderMethods;
31-
pub use self::asm::{AsmBuilderMethods, AsmMethods};
31+
pub use self::asm::{AsmBuilderMethods, AsmMethods, InlineAsmOperandRef};
3232
pub use self::backend::{Backend, BackendTypes, CodegenBackend, ExtraBackendMethods};
3333
pub use self::builder::{BuilderMethods, OverflowOp};
3434
pub use self::consts::ConstMethods;

src/rustllvm/RustWrapper.cpp

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -203,6 +203,10 @@ static Attribute::AttrKind fromRust(LLVMRustAttribute Kind) {
203203
return Attribute::OptimizeNone;
204204
case ReturnsTwice:
205205
return Attribute::ReturnsTwice;
206+
case ReadNone:
207+
return Attribute::ReadNone;
208+
case InaccessibleMemOnly:
209+
return Attribute::InaccessibleMemOnly;
206210
}
207211
report_fatal_error("bad AttributeKind");
208212
}

src/rustllvm/rustllvm.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -82,6 +82,8 @@ enum LLVMRustAttribute {
8282
NonLazyBind = 23,
8383
OptimizeNone = 24,
8484
ReturnsTwice = 25,
85+
ReadNone = 26,
86+
InaccessibleMemOnly = 27,
8587
};
8688

8789
typedef struct OpaqueRustString *RustStringRef;

0 commit comments

Comments
 (0)