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

Commit 1e7b246

Browse files
committed
Add asm! to MIR
1 parent 10510b5 commit 1e7b246

File tree

29 files changed

+544
-22
lines changed

29 files changed

+544
-22
lines changed

src/librustc_middle/mir/mod.rs

Lines changed: 104 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -28,6 +28,7 @@ use rustc_macros::HashStable;
2828
use rustc_serialize::{Decodable, Encodable};
2929
use rustc_span::symbol::Symbol;
3030
use rustc_span::{Span, DUMMY_SP};
31+
use rustc_target::asm::{InlineAsmOptions, InlineAsmRegOrRegClass, InlineAsmTemplatePiece};
3132
use std::borrow::Cow;
3233
use std::fmt::{self, Debug, Display, Formatter, Write};
3334
use std::ops::{Index, IndexMut};
@@ -1178,6 +1179,23 @@ pub enum TerminatorKind<'tcx> {
11781179
/// of the `remove_noop_landing_pads` and `no_landing_pads` passes.
11791180
unwind: Option<BasicBlock>,
11801181
},
1182+
1183+
/// Block ends with an inline assembly block. This is a terminator since
1184+
/// inline assembly is allowed to diverge.
1185+
InlineAsm {
1186+
/// The template for the inline assembly, with placeholders.
1187+
template: &'tcx [InlineAsmTemplatePiece],
1188+
1189+
/// The operands for the inline assembly, as `Operand`s or `Place`s.
1190+
operands: Vec<InlineAsmOperand<'tcx>>,
1191+
1192+
/// Miscellaneous options for the inline assembly.
1193+
options: InlineAsmOptions,
1194+
1195+
/// Destination block after the inline assembly returns, unless it is
1196+
/// diverging (InlineAsmOptions::NORETURN).
1197+
destination: Option<BasicBlock>,
1198+
},
11811199
}
11821200

11831201
/// Information about an assertion failure.
@@ -1192,6 +1210,34 @@ pub enum AssertKind<O> {
11921210
ResumedAfterPanic(GeneratorKind),
11931211
}
11941212

1213+
#[derive(Clone, Debug, PartialEq, RustcEncodable, RustcDecodable, HashStable, TypeFoldable)]
1214+
pub enum InlineAsmOperand<'tcx> {
1215+
In {
1216+
reg: InlineAsmRegOrRegClass,
1217+
value: Operand<'tcx>,
1218+
},
1219+
Out {
1220+
reg: InlineAsmRegOrRegClass,
1221+
late: bool,
1222+
place: Option<Place<'tcx>>,
1223+
},
1224+
InOut {
1225+
reg: InlineAsmRegOrRegClass,
1226+
late: bool,
1227+
in_value: Operand<'tcx>,
1228+
out_place: Option<Place<'tcx>>,
1229+
},
1230+
Const {
1231+
value: Operand<'tcx>,
1232+
},
1233+
SymFn {
1234+
value: Box<Constant<'tcx>>,
1235+
},
1236+
SymStatic {
1237+
value: Box<Constant<'tcx>>,
1238+
},
1239+
}
1240+
11951241
/// Type for MIR `Assert` terminator error messages.
11961242
pub type AssertMessage<'tcx> = AssertKind<Operand<'tcx>>;
11971243

@@ -1242,15 +1288,17 @@ impl<'tcx> TerminatorKind<'tcx> {
12421288
| GeneratorDrop
12431289
| Return
12441290
| Unreachable
1245-
| Call { destination: None, cleanup: None, .. } => None.into_iter().chain(&[]),
1291+
| Call { destination: None, cleanup: None, .. }
1292+
| InlineAsm { destination: None, .. } => None.into_iter().chain(&[]),
12461293
Goto { target: ref t }
12471294
| Call { destination: None, cleanup: Some(ref t), .. }
12481295
| Call { destination: Some((_, ref t)), cleanup: None, .. }
12491296
| Yield { resume: ref t, drop: None, .. }
12501297
| DropAndReplace { target: ref t, unwind: None, .. }
12511298
| Drop { target: ref t, unwind: None, .. }
12521299
| Assert { target: ref t, cleanup: None, .. }
1253-
| FalseUnwind { real_target: ref t, unwind: None } => Some(t).into_iter().chain(&[]),
1300+
| FalseUnwind { real_target: ref t, unwind: None }
1301+
| InlineAsm { destination: Some(ref t), .. } => Some(t).into_iter().chain(&[]),
12541302
Call { destination: Some((_, ref t)), cleanup: Some(ref u), .. }
12551303
| Yield { resume: ref t, drop: Some(ref u), .. }
12561304
| DropAndReplace { target: ref t, unwind: Some(ref u), .. }
@@ -1274,17 +1322,17 @@ impl<'tcx> TerminatorKind<'tcx> {
12741322
| GeneratorDrop
12751323
| Return
12761324
| Unreachable
1277-
| Call { destination: None, cleanup: None, .. } => None.into_iter().chain(&mut []),
1325+
| Call { destination: None, cleanup: None, .. }
1326+
| InlineAsm { destination: None, .. } => None.into_iter().chain(&mut []),
12781327
Goto { target: ref mut t }
12791328
| Call { destination: None, cleanup: Some(ref mut t), .. }
12801329
| Call { destination: Some((_, ref mut t)), cleanup: None, .. }
12811330
| Yield { resume: ref mut t, drop: None, .. }
12821331
| DropAndReplace { target: ref mut t, unwind: None, .. }
12831332
| Drop { target: ref mut t, unwind: None, .. }
12841333
| Assert { target: ref mut t, cleanup: None, .. }
1285-
| FalseUnwind { real_target: ref mut t, unwind: None } => {
1286-
Some(t).into_iter().chain(&mut [])
1287-
}
1334+
| FalseUnwind { real_target: ref mut t, unwind: None }
1335+
| InlineAsm { destination: Some(ref mut t), .. } => Some(t).into_iter().chain(&mut []),
12881336
Call { destination: Some((_, ref mut t)), cleanup: Some(ref mut u), .. }
12891337
| Yield { resume: ref mut t, drop: Some(ref mut u), .. }
12901338
| DropAndReplace { target: ref mut t, unwind: Some(ref mut u), .. }
@@ -1310,7 +1358,8 @@ impl<'tcx> TerminatorKind<'tcx> {
13101358
| TerminatorKind::GeneratorDrop
13111359
| TerminatorKind::Yield { .. }
13121360
| TerminatorKind::SwitchInt { .. }
1313-
| TerminatorKind::FalseEdges { .. } => None,
1361+
| TerminatorKind::FalseEdges { .. }
1362+
| TerminatorKind::InlineAsm { .. } => None,
13141363
TerminatorKind::Call { cleanup: ref unwind, .. }
13151364
| TerminatorKind::Assert { cleanup: ref unwind, .. }
13161365
| TerminatorKind::DropAndReplace { ref unwind, .. }
@@ -1329,7 +1378,8 @@ impl<'tcx> TerminatorKind<'tcx> {
13291378
| TerminatorKind::GeneratorDrop
13301379
| TerminatorKind::Yield { .. }
13311380
| TerminatorKind::SwitchInt { .. }
1332-
| TerminatorKind::FalseEdges { .. } => None,
1381+
| TerminatorKind::FalseEdges { .. }
1382+
| TerminatorKind::InlineAsm { .. } => None,
13331383
TerminatorKind::Call { cleanup: ref mut unwind, .. }
13341384
| TerminatorKind::Assert { cleanup: ref mut unwind, .. }
13351385
| TerminatorKind::DropAndReplace { ref mut unwind, .. }
@@ -1544,6 +1594,50 @@ impl<'tcx> TerminatorKind<'tcx> {
15441594
}
15451595
FalseEdges { .. } => write!(fmt, "falseEdges"),
15461596
FalseUnwind { .. } => write!(fmt, "falseUnwind"),
1597+
InlineAsm { template, ref operands, options, destination: _ } => {
1598+
write!(fmt, "asm!(\"{}\"", InlineAsmTemplatePiece::to_string(template))?;
1599+
for op in operands {
1600+
write!(fmt, ", ")?;
1601+
let print_late = |&late| if late { "late" } else { "" };
1602+
match op {
1603+
InlineAsmOperand::In { reg, value } => {
1604+
write!(fmt, "in({}) {:?}", reg, value)?;
1605+
}
1606+
InlineAsmOperand::Out { reg, late, place: Some(place) } => {
1607+
write!(fmt, "{}out({}) {:?}", print_late(late), reg, place)?;
1608+
}
1609+
InlineAsmOperand::Out { reg, late, place: None } => {
1610+
write!(fmt, "{}out({}) _", print_late(late), reg)?;
1611+
}
1612+
InlineAsmOperand::InOut {
1613+
reg,
1614+
late,
1615+
in_value,
1616+
out_place: Some(out_place),
1617+
} => {
1618+
write!(
1619+
fmt,
1620+
"in{}out({}) {:?} => {:?}",
1621+
print_late(late),
1622+
reg,
1623+
in_value,
1624+
out_place
1625+
)?;
1626+
}
1627+
InlineAsmOperand::InOut { reg, late, in_value, out_place: None } => {
1628+
write!(fmt, "in{}out({}) {:?} => _", print_late(late), reg, in_value)?;
1629+
}
1630+
InlineAsmOperand::Const { value } => {
1631+
write!(fmt, "const {:?}", value)?;
1632+
}
1633+
InlineAsmOperand::SymFn { value }
1634+
| InlineAsmOperand::SymStatic { value } => {
1635+
write!(fmt, "sym {:?}", value)?;
1636+
}
1637+
}
1638+
}
1639+
write!(fmt, ", options({:?}))", options)
1640+
}
15471641
}
15481642
}
15491643

@@ -1586,6 +1680,8 @@ impl<'tcx> TerminatorKind<'tcx> {
15861680
FalseEdges { .. } => vec!["real".into(), "imaginary".into()],
15871681
FalseUnwind { unwind: Some(_), .. } => vec!["real".into(), "cleanup".into()],
15881682
FalseUnwind { unwind: None, .. } => vec!["real".into()],
1683+
InlineAsm { destination: Some(_), .. } => vec!["".into()],
1684+
InlineAsm { destination: None, .. } => vec![],
15891685
}
15901686
}
15911687
}

src/librustc_middle/mir/type_foldable.rs

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -78,6 +78,9 @@ impl<'tcx> TypeFoldable<'tcx> for Terminator<'tcx> {
7878
FalseEdges { real_target, imaginary_target }
7979
}
8080
FalseUnwind { real_target, unwind } => FalseUnwind { real_target, unwind },
81+
InlineAsm { template, ref operands, options, destination } => {
82+
InlineAsm { template, operands: operands.fold_with(folder), options, destination }
83+
}
8184
};
8285
Terminator { source_info: self.source_info, kind }
8386
}
@@ -120,6 +123,7 @@ impl<'tcx> TypeFoldable<'tcx> for Terminator<'tcx> {
120123
false
121124
}
122125
}
126+
InlineAsm { ref operands, .. } => operands.visit_with(visitor),
123127
Goto { .. }
124128
| Resume
125129
| Abort

src/librustc_middle/mir/visit.rs

Lines changed: 38 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -531,6 +531,44 @@ macro_rules! make_mir_visitor {
531531
);
532532
}
533533

534+
TerminatorKind::InlineAsm {
535+
template: _,
536+
operands,
537+
options: _,
538+
destination: _,
539+
} => {
540+
for op in operands {
541+
match op {
542+
InlineAsmOperand::In { value, .. }
543+
| InlineAsmOperand::Const { value } => {
544+
self.visit_operand(value, source_location);
545+
}
546+
InlineAsmOperand::Out { place, .. } => {
547+
if let Some(place) = place {
548+
self.visit_place(
549+
place,
550+
PlaceContext::MutatingUse(MutatingUseContext::Store),
551+
source_location,
552+
);
553+
}
554+
}
555+
InlineAsmOperand::InOut { in_value, out_place, .. } => {
556+
self.visit_operand(in_value, source_location);
557+
if let Some(out_place) = out_place {
558+
self.visit_place(
559+
out_place,
560+
PlaceContext::MutatingUse(MutatingUseContext::Store),
561+
source_location,
562+
);
563+
}
564+
}
565+
InlineAsmOperand::SymFn { value }
566+
| InlineAsmOperand::SymStatic { value } => {
567+
self.visit_constant(value, source_location);
568+
}
569+
}
570+
}
571+
}
534572
}
535573
}
536574

src/librustc_middle/ty/structural_impls.rs

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -267,6 +267,9 @@ CloneTypeFoldableAndLiftImpls! {
267267
::rustc_hir::MatchSource,
268268
::rustc_hir::Mutability,
269269
::rustc_hir::Unsafety,
270+
::rustc_target::asm::InlineAsmOptions,
271+
::rustc_target::asm::InlineAsmRegOrRegClass,
272+
::rustc_target::asm::InlineAsmTemplatePiece,
270273
::rustc_target::spec::abi::Abi,
271274
crate::mir::Local,
272275
crate::mir::Promoted,

src/librustc_mir/borrow_check/invalidation.rs

Lines changed: 24 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,8 @@
11
use rustc_data_structures::graph::dominators::Dominators;
22
use rustc_middle::mir::visit::Visitor;
3-
use rustc_middle::mir::TerminatorKind;
43
use rustc_middle::mir::{BasicBlock, Body, Location, Place, Rvalue};
54
use rustc_middle::mir::{BorrowKind, Mutability, Operand};
5+
use rustc_middle::mir::{InlineAsmOperand, TerminatorKind};
66
use rustc_middle::mir::{Statement, StatementKind};
77
use rustc_middle::ty::TyCtxt;
88

@@ -183,6 +183,29 @@ impl<'cx, 'tcx> Visitor<'tcx> for InvalidationGenerator<'cx, 'tcx> {
183183
}
184184
}
185185
}
186+
TerminatorKind::InlineAsm { template: _, ref operands, options: _, destination: _ } => {
187+
for op in operands {
188+
match *op {
189+
InlineAsmOperand::In { reg: _, ref value }
190+
| InlineAsmOperand::Const { ref value } => {
191+
self.consume_operand(location, value);
192+
}
193+
InlineAsmOperand::Out { reg: _, late: _, place, .. } => {
194+
if let Some(place) = place {
195+
self.mutate_place(location, place, Shallow(None), JustWrite);
196+
}
197+
}
198+
InlineAsmOperand::InOut { reg: _, late: _, ref in_value, out_place } => {
199+
self.consume_operand(location, in_value);
200+
if let Some(out_place) = out_place {
201+
self.mutate_place(location, out_place, Shallow(None), JustWrite);
202+
}
203+
}
204+
InlineAsmOperand::SymFn { value: _ }
205+
| InlineAsmOperand::SymStatic { value: _ } => {}
206+
}
207+
}
208+
}
186209
TerminatorKind::Goto { target: _ }
187210
| TerminatorKind::Abort
188211
| TerminatorKind::Unreachable

src/librustc_mir/borrow_check/mod.rs

Lines changed: 39 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,7 @@ use rustc_middle::mir::{
1717
};
1818
use rustc_middle::mir::{AggregateKind, BasicBlock, BorrowCheckResult, BorrowKind};
1919
use rustc_middle::mir::{Field, ProjectionElem, Promoted, Rvalue, Statement, StatementKind};
20-
use rustc_middle::mir::{Terminator, TerminatorKind};
20+
use rustc_middle::mir::{InlineAsmOperand, Terminator, TerminatorKind};
2121
use rustc_middle::ty::query::Providers;
2222
use rustc_middle::ty::{self, RegionVid, TyCtxt};
2323
use rustc_session::lint::builtin::{MUTABLE_BORROW_RESERVATION_CONFLICT, UNUSED_MUT};
@@ -724,6 +724,42 @@ impl<'cx, 'tcx> dataflow::ResultsVisitor<'cx, 'tcx> for MirBorrowckCtxt<'cx, 'tc
724724
self.mutate_place(loc, (resume_arg, span), Deep, JustWrite, flow_state);
725725
}
726726

727+
TerminatorKind::InlineAsm { template: _, ref operands, options: _, destination: _ } => {
728+
for op in operands {
729+
match *op {
730+
InlineAsmOperand::In { reg: _, ref value }
731+
| InlineAsmOperand::Const { ref value } => {
732+
self.consume_operand(loc, (value, span), flow_state);
733+
}
734+
InlineAsmOperand::Out { reg: _, late: _, place, .. } => {
735+
if let Some(place) = place {
736+
self.mutate_place(
737+
loc,
738+
(place, span),
739+
Shallow(None),
740+
JustWrite,
741+
flow_state,
742+
);
743+
}
744+
}
745+
InlineAsmOperand::InOut { reg: _, late: _, ref in_value, out_place } => {
746+
self.consume_operand(loc, (in_value, span), flow_state);
747+
if let Some(out_place) = out_place {
748+
self.mutate_place(
749+
loc,
750+
(out_place, span),
751+
Shallow(None),
752+
JustWrite,
753+
flow_state,
754+
);
755+
}
756+
}
757+
InlineAsmOperand::SymFn { value: _ }
758+
| InlineAsmOperand::SymStatic { value: _ } => {}
759+
}
760+
}
761+
}
762+
727763
TerminatorKind::Goto { target: _ }
728764
| TerminatorKind::Abort
729765
| TerminatorKind::Unreachable
@@ -778,7 +814,8 @@ impl<'cx, 'tcx> dataflow::ResultsVisitor<'cx, 'tcx> for MirBorrowckCtxt<'cx, 'tc
778814
| TerminatorKind::FalseUnwind { real_target: _, unwind: _ }
779815
| TerminatorKind::Goto { .. }
780816
| TerminatorKind::SwitchInt { .. }
781-
| TerminatorKind::Unreachable => {}
817+
| TerminatorKind::Unreachable
818+
| TerminatorKind::InlineAsm { .. } => {}
782819
}
783820
}
784821
}

src/librustc_mir/borrow_check/type_check/mod.rs

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1548,7 +1548,8 @@ impl<'a, 'tcx> TypeChecker<'a, 'tcx> {
15481548
| TerminatorKind::Unreachable
15491549
| TerminatorKind::Drop { .. }
15501550
| TerminatorKind::FalseEdges { .. }
1551-
| TerminatorKind::FalseUnwind { .. } => {
1551+
| TerminatorKind::FalseUnwind { .. }
1552+
| TerminatorKind::InlineAsm { .. } => {
15521553
// no checks needed for these
15531554
}
15541555

@@ -1855,6 +1856,11 @@ impl<'a, 'tcx> TypeChecker<'a, 'tcx> {
18551856
self.assert_iscleanup(body, block_data, unwind, true);
18561857
}
18571858
}
1859+
TerminatorKind::InlineAsm { ref destination, .. } => {
1860+
if let &Some(target) = destination {
1861+
self.assert_iscleanup(body, block_data, target, is_cleanup);
1862+
}
1863+
}
18581864
}
18591865
}
18601866

src/librustc_mir/dataflow/framework/direction.rs

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -482,6 +482,12 @@ impl Direction for Forward {
482482
}
483483
}
484484

485+
InlineAsm { template: _, operands: _, options: _, destination } => {
486+
if let Some(target) = destination {
487+
propagate(target, exit_state);
488+
}
489+
}
490+
485491
SwitchInt { ref targets, ref values, ref discr, switch_ty: _ } => {
486492
let enum_ = discr
487493
.place()

0 commit comments

Comments
 (0)