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

Commit 342a64c

Browse files
committed
Check that asm const operands are actually constants
1 parent 1e7b246 commit 342a64c

File tree

1 file changed

+65
-16
lines changed

1 file changed

+65
-16
lines changed

src/librustc_mir/transform/promote_consts.rs

Lines changed: 65 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -113,14 +113,17 @@ pub enum Candidate {
113113
/// the attribute currently provides the semantic requirement that arguments
114114
/// must be constant.
115115
Argument { bb: BasicBlock, index: usize },
116+
117+
/// `const` operand in asm!.
118+
InlineAsm { bb: BasicBlock, index: usize },
116119
}
117120

118121
impl Candidate {
119122
/// Returns `true` if we should use the "explicit" rules for promotability for this `Candidate`.
120123
fn forces_explicit_promotion(&self) -> bool {
121124
match self {
122125
Candidate::Ref(_) | Candidate::Repeat(_) => false,
123-
Candidate::Argument { .. } => true,
126+
Candidate::Argument { .. } | Candidate::InlineAsm { .. } => true,
124127
}
125128
}
126129
}
@@ -216,25 +219,39 @@ impl<'tcx> Visitor<'tcx> for Collector<'_, 'tcx> {
216219
fn visit_terminator_kind(&mut self, kind: &TerminatorKind<'tcx>, location: Location) {
217220
self.super_terminator_kind(kind, location);
218221

219-
if let TerminatorKind::Call { ref func, .. } = *kind {
220-
if let ty::FnDef(def_id, _) = func.ty(self.ccx.body, self.ccx.tcx).kind {
221-
let fn_sig = self.ccx.tcx.fn_sig(def_id);
222-
if let Abi::RustIntrinsic | Abi::PlatformIntrinsic = fn_sig.abi() {
223-
let name = self.ccx.tcx.item_name(def_id);
224-
// FIXME(eddyb) use `#[rustc_args_required_const(2)]` for shuffles.
225-
if name.as_str().starts_with("simd_shuffle") {
226-
self.candidates.push(Candidate::Argument { bb: location.block, index: 2 });
222+
match *kind {
223+
TerminatorKind::Call { ref func, .. } => {
224+
if let ty::FnDef(def_id, _) = func.ty(self.ccx.body, self.ccx.tcx).kind {
225+
let fn_sig = self.ccx.tcx.fn_sig(def_id);
226+
if let Abi::RustIntrinsic | Abi::PlatformIntrinsic = fn_sig.abi() {
227+
let name = self.ccx.tcx.item_name(def_id);
228+
// FIXME(eddyb) use `#[rustc_args_required_const(2)]` for shuffles.
229+
if name.as_str().starts_with("simd_shuffle") {
230+
self.candidates
231+
.push(Candidate::Argument { bb: location.block, index: 2 });
232+
233+
return; // Don't double count `simd_shuffle` candidates
234+
}
235+
}
227236

228-
return; // Don't double count `simd_shuffle` candidates
237+
if let Some(constant_args) = args_required_const(self.ccx.tcx, def_id) {
238+
for index in constant_args {
239+
self.candidates.push(Candidate::Argument { bb: location.block, index });
240+
}
229241
}
230242
}
231-
232-
if let Some(constant_args) = args_required_const(self.ccx.tcx, def_id) {
233-
for index in constant_args {
234-
self.candidates.push(Candidate::Argument { bb: location.block, index });
243+
}
244+
TerminatorKind::InlineAsm { ref operands, .. } => {
245+
for (index, op) in operands.iter().enumerate() {
246+
match op {
247+
InlineAsmOperand::Const { .. } => {
248+
self.candidates.push(Candidate::InlineAsm { bb: location.block, index })
249+
}
250+
_ => {}
235251
}
236252
}
237253
}
254+
_ => {}
238255
}
239256
}
240257

@@ -402,6 +419,18 @@ impl<'tcx> Validator<'_, 'tcx> {
402419
_ => bug!(),
403420
}
404421
}
422+
Candidate::InlineAsm { bb, index } => {
423+
assert!(self.explicit);
424+
425+
let terminator = self.body[bb].terminator();
426+
match &terminator.kind {
427+
TerminatorKind::InlineAsm { operands, .. } => match &operands[index] {
428+
InlineAsmOperand::Const { value } => self.validate_operand(value),
429+
_ => bug!(),
430+
},
431+
_ => bug!(),
432+
}
433+
}
405434
}
406435
}
407436

@@ -747,7 +776,9 @@ pub fn validate_candidates(
747776
}
748777

749778
match candidate {
750-
Candidate::Argument { bb, index } if !is_promotable => {
779+
Candidate::Argument { bb, index } | Candidate::InlineAsm { bb, index }
780+
if !is_promotable =>
781+
{
751782
let span = ccx.body[bb].terminator().source_info.span;
752783
let msg = format!("argument {} is required to be a constant", index + 1);
753784
ccx.tcx.sess.span_err(span, &msg);
@@ -1024,6 +1055,24 @@ impl<'a, 'tcx> Promoter<'a, 'tcx> {
10241055
_ => bug!(),
10251056
}
10261057
}
1058+
Candidate::InlineAsm { bb, index } => {
1059+
let terminator = blocks[bb].terminator_mut();
1060+
match terminator.kind {
1061+
TerminatorKind::InlineAsm { ref mut operands, .. } => {
1062+
match &mut operands[index] {
1063+
InlineAsmOperand::Const { ref mut value } => {
1064+
let ty = value.ty(local_decls, self.tcx);
1065+
let span = terminator.source_info.span;
1066+
1067+
Rvalue::Use(mem::replace(value, promoted_operand(ty, span)))
1068+
}
1069+
_ => bug!(),
1070+
}
1071+
}
1072+
1073+
_ => bug!(),
1074+
}
1075+
}
10271076
}
10281077
};
10291078

@@ -1080,7 +1129,7 @@ pub fn promote_candidates<'tcx>(
10801129
}
10811130
}
10821131
}
1083-
Candidate::Argument { .. } => {}
1132+
Candidate::Argument { .. } | Candidate::InlineAsm { .. } => {}
10841133
}
10851134

10861135
// Declare return place local so that `mir::Body::new` doesn't complain.

0 commit comments

Comments
 (0)