Skip to content

Commit d3cba25

Browse files
committed
Auto merge of #71192 - oli-obk:eager_alloc_id_canonicalization, r=wesleywiser
Make TLS accesses explicit in MIR r? @rust-lang/wg-mir-opt cc @RalfJung @vakaras for miri thread locals cc @bjorn3 for cranelift fixes #70685
2 parents b85e3fe + 0aa7f4d commit d3cba25

File tree

31 files changed

+157
-23
lines changed

31 files changed

+157
-23
lines changed

src/librustc_codegen_llvm/common.rs

+1
Original file line numberDiff line numberDiff line change
@@ -259,6 +259,7 @@ impl ConstMethods<'tcx> for CodegenCx<'ll, 'tcx> {
259259
GlobalAlloc::Function(fn_instance) => self.get_fn_addr(fn_instance),
260260
GlobalAlloc::Static(def_id) => {
261261
assert!(self.tcx.is_static(def_id));
262+
assert!(!self.tcx.is_thread_local_static(def_id));
262263
self.get_static(def_id)
263264
}
264265
};

src/librustc_codegen_ssa/mir/rvalue.rs

+8
Original file line numberDiff line numberDiff line change
@@ -522,6 +522,13 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> {
522522
let operand = OperandRef { val: OperandValue::Immediate(val), layout: box_layout };
523523
(bx, operand)
524524
}
525+
mir::Rvalue::ThreadLocalRef(def_id) => {
526+
assert!(bx.cx().tcx().is_static(def_id));
527+
let static_ = bx.get_static(def_id);
528+
let layout = bx.layout_of(bx.cx().tcx().static_ptr_ty(def_id));
529+
let operand = OperandRef::from_immediate_or_packed_pair(&mut bx, static_, layout);
530+
(bx, operand)
531+
}
525532
mir::Rvalue::Use(ref operand) => {
526533
let operand = self.codegen_operand(&mut bx, operand);
527534
(bx, operand)
@@ -745,6 +752,7 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> {
745752
mir::Rvalue::UnaryOp(..) |
746753
mir::Rvalue::Discriminant(..) |
747754
mir::Rvalue::NullaryOp(..) |
755+
mir::Rvalue::ThreadLocalRef(_) |
748756
mir::Rvalue::Use(..) => // (*)
749757
true,
750758
mir::Rvalue::Repeat(..) |

src/librustc_middle/mir/interpret/error.rs

+3
Original file line numberDiff line numberDiff line change
@@ -513,6 +513,8 @@ pub enum UnsupportedOpInfo {
513513
//
514514
/// Encountered raw bytes where we needed a pointer.
515515
ReadBytesAsPointer,
516+
/// Accessing thread local statics
517+
ThreadLocalStatic(DefId),
516518
}
517519

518520
impl fmt::Display for UnsupportedOpInfo {
@@ -526,6 +528,7 @@ impl fmt::Display for UnsupportedOpInfo {
526528
NoMirFor(did) => write!(f, "no MIR body is available for {:?}", did),
527529
ReadPointerAsBytes => write!(f, "unable to turn pointer into raw bytes",),
528530
ReadBytesAsPointer => write!(f, "unable to turn bytes into a pointer"),
531+
ThreadLocalStatic(did) => write!(f, "accessing thread local static {:?}", did),
529532
}
530533
}
531534
}

src/librustc_middle/mir/interpret/mod.rs

+1
Original file line numberDiff line numberDiff line change
@@ -209,6 +209,7 @@ pub fn specialized_encode_alloc_id<'tcx, E: Encoder>(
209209
fn_instance.encode(encoder)?;
210210
}
211211
GlobalAlloc::Static(did) => {
212+
assert!(!tcx.is_thread_local_static(did));
212213
// References to statics doesn't need to know about their allocations,
213214
// just about its `DefId`.
214215
AllocDiscriminant::Static.encode(encoder)?;

src/librustc_middle/mir/mod.rs

+13-1
Original file line numberDiff line numberDiff line change
@@ -2214,6 +2214,11 @@ pub enum Rvalue<'tcx> {
22142214
/// &x or &mut x
22152215
Ref(Region<'tcx>, BorrowKind, Place<'tcx>),
22162216

2217+
/// Accessing a thread local static. This is inherently a runtime operation, even if llvm
2218+
/// treats it as an access to a static. This `Rvalue` yields a reference to the thread local
2219+
/// static.
2220+
ThreadLocalRef(DefId),
2221+
22172222
/// Create a raw pointer to the given place
22182223
/// Can be generated by raw address of expressions (`&raw const x`),
22192224
/// or when casting a reference to a raw pointer.
@@ -2353,6 +2358,10 @@ impl<'tcx> Debug for Rvalue<'tcx> {
23532358
UnaryOp(ref op, ref a) => write!(fmt, "{:?}({:?})", op, a),
23542359
Discriminant(ref place) => write!(fmt, "discriminant({:?})", place),
23552360
NullaryOp(ref op, ref t) => write!(fmt, "{:?}({:?})", op, t),
2361+
ThreadLocalRef(did) => ty::tls::with(|tcx| {
2362+
let muta = tcx.static_mutability(did).unwrap().prefix_str();
2363+
write!(fmt, "&/*tls*/ {}{}", muta, tcx.def_path_str(did))
2364+
}),
23562365
Ref(region, borrow_kind, ref place) => {
23572366
let kind_str = match borrow_kind {
23582367
BorrowKind::Shared => "",
@@ -2506,7 +2515,10 @@ impl Constant<'tcx> {
25062515
pub fn check_static_ptr(&self, tcx: TyCtxt<'_>) -> Option<DefId> {
25072516
match self.literal.val.try_to_scalar() {
25082517
Some(Scalar::Ptr(ptr)) => match tcx.global_alloc(ptr.alloc_id) {
2509-
GlobalAlloc::Static(def_id) => Some(def_id),
2518+
GlobalAlloc::Static(def_id) => {
2519+
assert!(!tcx.is_thread_local_static(def_id));
2520+
Some(def_id)
2521+
}
25102522
_ => None,
25112523
},
25122524
_ => None,

src/librustc_middle/mir/tcx.rs

+7
Original file line numberDiff line numberDiff line change
@@ -151,6 +151,13 @@ impl<'tcx> Rvalue<'tcx> {
151151
Rvalue::Repeat(ref operand, count) => {
152152
tcx.mk_ty(ty::Array(operand.ty(local_decls, tcx), count))
153153
}
154+
Rvalue::ThreadLocalRef(did) => {
155+
if tcx.is_mutable_static(did) {
156+
tcx.mk_mut_ptr(tcx.type_of(did))
157+
} else {
158+
tcx.mk_imm_ref(tcx.lifetimes.re_static, tcx.type_of(did))
159+
}
160+
}
154161
Rvalue::Ref(reg, bk, ref place) => {
155162
let place_ty = place.ty(local_decls, tcx).ty;
156163
tcx.mk_ref(reg, ty::TypeAndMut { ty: place_ty, mutbl: bk.to_mutbl_lossy() })

src/librustc_middle/mir/type_foldable.rs

+2
Original file line numberDiff line numberDiff line change
@@ -177,6 +177,7 @@ impl<'tcx> TypeFoldable<'tcx> for Rvalue<'tcx> {
177177
match *self {
178178
Use(ref op) => Use(op.fold_with(folder)),
179179
Repeat(ref op, len) => Repeat(op.fold_with(folder), len),
180+
ThreadLocalRef(did) => ThreadLocalRef(did.fold_with(folder)),
180181
Ref(region, bk, ref place) => {
181182
Ref(region.fold_with(folder), bk, place.fold_with(folder))
182183
}
@@ -220,6 +221,7 @@ impl<'tcx> TypeFoldable<'tcx> for Rvalue<'tcx> {
220221
match *self {
221222
Use(ref op) => op.visit_with(visitor),
222223
Repeat(ref op, _) => op.visit_with(visitor),
224+
ThreadLocalRef(did) => did.visit_with(visitor),
223225
Ref(region, _, ref place) => region.visit_with(visitor) || place.visit_with(visitor),
224226
AddressOf(_, ref place) => place.visit_with(visitor),
225227
Len(ref place) => place.visit_with(visitor),

src/librustc_middle/mir/visit.rs

+2
Original file line numberDiff line numberDiff line change
@@ -601,6 +601,8 @@ macro_rules! make_mir_visitor {
601601
self.visit_operand(value, location);
602602
}
603603

604+
Rvalue::ThreadLocalRef(_) => {}
605+
604606
Rvalue::Ref(r, bk, path) => {
605607
self.visit_region(r, location);
606608
let ctx = match bk {

src/librustc_mir/borrow_check/invalidation.rs

+2
Original file line numberDiff line numberDiff line change
@@ -301,6 +301,8 @@ impl<'cx, 'tcx> InvalidationGenerator<'cx, 'tcx> {
301301
self.access_place(location, place, access_kind, LocalMutationIsAllowed::No);
302302
}
303303

304+
Rvalue::ThreadLocalRef(_) => {}
305+
304306
Rvalue::Use(ref operand)
305307
| Rvalue::Repeat(ref operand, _)
306308
| Rvalue::UnaryOp(_ /*un_op*/, ref operand)

src/librustc_mir/borrow_check/mod.rs

+2
Original file line numberDiff line numberDiff line change
@@ -1296,6 +1296,8 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> {
12961296
);
12971297
}
12981298

1299+
Rvalue::ThreadLocalRef(_) => {}
1300+
12991301
Rvalue::Use(ref operand)
13001302
| Rvalue::Repeat(ref operand, _)
13011303
| Rvalue::UnaryOp(_ /*un_op*/, ref operand)

src/librustc_mir/borrow_check/type_check/mod.rs

+2
Original file line numberDiff line numberDiff line change
@@ -2353,6 +2353,7 @@ impl<'a, 'tcx> TypeChecker<'a, 'tcx> {
23532353
}
23542354

23552355
Rvalue::AddressOf(..)
2356+
| Rvalue::ThreadLocalRef(..)
23562357
| Rvalue::Use(..)
23572358
| Rvalue::Len(..)
23582359
| Rvalue::BinaryOp(..)
@@ -2368,6 +2369,7 @@ impl<'a, 'tcx> TypeChecker<'a, 'tcx> {
23682369
fn rvalue_user_ty(&self, rvalue: &Rvalue<'tcx>) -> Option<UserTypeAnnotationIndex> {
23692370
match rvalue {
23702371
Rvalue::Use(_)
2372+
| Rvalue::ThreadLocalRef(_)
23712373
| Rvalue::Repeat(..)
23722374
| Rvalue::Ref(..)
23732375
| Rvalue::AddressOf(..)

src/librustc_mir/dataflow/impls/borrowed_locals.rs

+1
Original file line numberDiff line numberDiff line change
@@ -176,6 +176,7 @@ where
176176

177177
mir::Rvalue::Cast(..)
178178
| mir::Rvalue::Use(..)
179+
| mir::Rvalue::ThreadLocalRef(..)
179180
| mir::Rvalue::Repeat(..)
180181
| mir::Rvalue::Len(..)
181182
| mir::Rvalue::BinaryOp(..)

src/librustc_mir/dataflow/move_paths/builder.rs

+1
Original file line numberDiff line numberDiff line change
@@ -324,6 +324,7 @@ impl<'b, 'a, 'tcx> Gatherer<'b, 'a, 'tcx> {
324324

325325
fn gather_rvalue(&mut self, rvalue: &Rvalue<'tcx>) {
326326
match *rvalue {
327+
Rvalue::ThreadLocalRef(_) => {} // not-a-move
327328
Rvalue::Use(ref operand)
328329
| Rvalue::Repeat(ref operand, _)
329330
| Rvalue::Cast(_, ref operand, _)

src/librustc_mir/interpret/machine.rs

+7
Original file line numberDiff line numberDiff line change
@@ -358,6 +358,13 @@ pub trait Machine<'mir, 'tcx>: Sized {
358358
_mem: &Memory<'mir, 'tcx, Self>,
359359
_ptr: Pointer<Self::PointerTag>,
360360
) -> InterpResult<'tcx, u64>;
361+
362+
fn thread_local_alloc_id(
363+
_ecx: &mut InterpCx<'mir, 'tcx, Self>,
364+
did: DefId,
365+
) -> InterpResult<'tcx, AllocId> {
366+
throw_unsup!(ThreadLocalStatic(did))
367+
}
361368
}
362369

363370
// A lot of the flexibility above is just needed for `Miri`, but all "compile-time" machines

src/librustc_mir/interpret/memory.rs

+2
Original file line numberDiff line numberDiff line change
@@ -437,6 +437,7 @@ impl<'mir, 'tcx, M: Machine<'mir, 'tcx>> Memory<'mir, 'tcx, M> {
437437
Some(GlobalAlloc::Function(..)) => throw_ub!(DerefFunctionPointer(id)),
438438
None => throw_ub!(PointerUseAfterFree(id)),
439439
Some(GlobalAlloc::Static(def_id)) => {
440+
assert!(!tcx.is_thread_local_static(def_id));
440441
// Notice that every static has two `AllocId` that will resolve to the same
441442
// thing here: one maps to `GlobalAlloc::Static`, this is the "lazy" ID,
442443
// and the other one is maps to `GlobalAlloc::Memory`, this is returned by
@@ -592,6 +593,7 @@ impl<'mir, 'tcx, M: Machine<'mir, 'tcx>> Memory<'mir, 'tcx, M> {
592593
// be held throughout the match.
593594
match self.tcx.get_global_alloc(id) {
594595
Some(GlobalAlloc::Static(did)) => {
596+
assert!(!self.tcx.is_thread_local_static(did));
595597
// Use size and align of the type.
596598
let ty = self.tcx.type_of(did);
597599
let layout = self.tcx.layout_of(ParamEnv::empty().and(ty)).unwrap();

src/librustc_mir/interpret/step.rs

+6
Original file line numberDiff line numberDiff line change
@@ -141,6 +141,12 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> {
141141

142142
use rustc_middle::mir::Rvalue::*;
143143
match *rvalue {
144+
ThreadLocalRef(did) => {
145+
let id = M::thread_local_alloc_id(self, did)?;
146+
let val = Scalar::Ptr(self.tag_global_base_pointer(id.into()));
147+
self.write_scalar(val, dest)?;
148+
}
149+
144150
Use(ref operand) => {
145151
// Avoid recomputing the layout
146152
let op = self.eval_operand(operand, Some(dest.layout))?;

src/librustc_mir/interpret/validity.rs

+1
Original file line numberDiff line numberDiff line change
@@ -418,6 +418,7 @@ impl<'rt, 'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> ValidityVisitor<'rt, 'mir, '
418418
// Skip validation entirely for some external statics
419419
let alloc_kind = self.ecx.tcx.get_global_alloc(ptr.alloc_id);
420420
if let Some(GlobalAlloc::Static(did)) = alloc_kind {
421+
assert!(!self.ecx.tcx.is_thread_local_static(did));
421422
// See const_eval::machine::MemoryExtra::can_access_statics for why
422423
// this check is so important.
423424
// This check is reachable when the const just referenced the static,

src/librustc_mir/monomorphize/collector.rs

+1
Original file line numberDiff line numberDiff line change
@@ -1143,6 +1143,7 @@ fn create_mono_items_for_default_impls<'tcx>(
11431143
fn collect_miri<'tcx>(tcx: TyCtxt<'tcx>, alloc_id: AllocId, output: &mut Vec<MonoItem<'tcx>>) {
11441144
match tcx.global_alloc(alloc_id) {
11451145
GlobalAlloc::Static(def_id) => {
1146+
assert!(!tcx.is_thread_local_static(def_id));
11461147
let instance = Instance::mono(tcx, def_id);
11471148
if should_monomorphize_locally(tcx, &instance) {
11481149
trace!("collecting static {:?}", def_id);

src/librustc_mir/transform/check_consts/qualifs.rs

+3-1
Original file line numberDiff line numberDiff line change
@@ -153,7 +153,9 @@ where
153153
F: FnMut(Local) -> bool,
154154
{
155155
match rvalue {
156-
Rvalue::NullaryOp(..) => Q::in_any_value_of_ty(cx, rvalue.ty(cx.body, cx.tcx)),
156+
Rvalue::ThreadLocalRef(_) | Rvalue::NullaryOp(..) => {
157+
Q::in_any_value_of_ty(cx, rvalue.ty(cx.body, cx.tcx))
158+
}
157159

158160
Rvalue::Discriminant(place) | Rvalue::Len(place) => {
159161
in_place::<Q, _>(cx, in_local, place.as_ref())

src/librustc_mir/transform/check_consts/validation.rs

+7-5
Original file line numberDiff line numberDiff line change
@@ -263,11 +263,11 @@ impl Validator<'mir, 'tcx> {
263263
}
264264

265265
fn check_static(&mut self, def_id: DefId, span: Span) {
266-
if self.tcx.is_thread_local_static(def_id) {
267-
self.check_op_spanned(ops::ThreadLocalAccess, span)
268-
} else {
269-
self.check_op_spanned(ops::StaticAccess, span)
270-
}
266+
assert!(
267+
!self.tcx.is_thread_local_static(def_id),
268+
"tls access is checked in `Rvalue::ThreadLocalRef"
269+
);
270+
self.check_op_spanned(ops::StaticAccess, span)
271271
}
272272
}
273273

@@ -332,6 +332,8 @@ impl Visitor<'tcx> for Validator<'mir, 'tcx> {
332332
self.super_rvalue(rvalue, location);
333333

334334
match *rvalue {
335+
Rvalue::ThreadLocalRef(_) => self.check_op(ops::ThreadLocalAccess),
336+
335337
Rvalue::Use(_)
336338
| Rvalue::Repeat(..)
337339
| Rvalue::UnaryOp(UnOp::Neg, _)

src/librustc_mir/transform/promote_consts.rs

+2
Original file line numberDiff line numberDiff line change
@@ -603,6 +603,8 @@ impl<'tcx> Validator<'_, 'tcx> {
603603
}
604604

605605
match rvalue {
606+
Rvalue::ThreadLocalRef(_) => Err(Unpromotable),
607+
606608
Rvalue::NullaryOp(..) => Ok(()),
607609

608610
Rvalue::Discriminant(place) | Rvalue::Len(place) => self.validate_place(place.as_ref()),

src/librustc_mir/transform/qualify_min_const_fn.rs

+3
Original file line numberDiff line numberDiff line change
@@ -156,6 +156,9 @@ fn check_rvalue(
156156
span: Span,
157157
) -> McfResult {
158158
match rvalue {
159+
Rvalue::ThreadLocalRef(_) => {
160+
Err((span, "cannot access thread local storage in const fn".into()))
161+
}
159162
Rvalue::Repeat(operand, _) | Rvalue::Use(operand) => {
160163
check_operand(tcx, operand, span, def_id, body)
161164
}

src/librustc_mir_build/build/expr/as_place.rs

+1
Original file line numberDiff line numberDiff line change
@@ -258,6 +258,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
258258
| ExprKind::InlineAsm { .. }
259259
| ExprKind::LlvmInlineAsm { .. }
260260
| ExprKind::Yield { .. }
261+
| ExprKind::ThreadLocalRef(_)
261262
| ExprKind::Call { .. } => {
262263
// these are not places, so we need to make a temporary.
263264
debug_assert!(match Category::of(&expr.kind) {

src/librustc_mir_build/build/expr/as_rvalue.rs

+1
Original file line numberDiff line numberDiff line change
@@ -53,6 +53,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
5353
let source_info = this.source_info(expr_span);
5454

5555
match expr.kind {
56+
ExprKind::ThreadLocalRef(did) => block.and(Rvalue::ThreadLocalRef(did)),
5657
ExprKind::Scope { region_scope, lint_level, value } => {
5758
let region_scope = (region_scope, source_info);
5859
this.in_scope(region_scope, lint_level, |this| this.as_rvalue(block, scope, value))

src/librustc_mir_build/build/expr/as_temp.rs

+12-4
Original file line numberDiff line numberDiff line change
@@ -63,10 +63,18 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
6363
if let Some(tail_info) = this.block_context.currently_in_block_tail() {
6464
local_decl = local_decl.block_tail(tail_info);
6565
}
66-
if let ExprKind::StaticRef { def_id, .. } = expr.kind {
67-
let is_thread_local = this.hir.tcx().is_thread_local_static(def_id);
68-
local_decl.internal = true;
69-
local_decl.local_info = Some(box LocalInfo::StaticRef { def_id, is_thread_local });
66+
match expr.kind {
67+
ExprKind::StaticRef { def_id, .. } => {
68+
assert!(!this.hir.tcx().is_thread_local_static(def_id));
69+
local_decl.internal = true;
70+
local_decl.local_info = Some(box LocalInfo::StaticRef { def_id, is_thread_local: false });
71+
}
72+
ExprKind::ThreadLocalRef(def_id) => {
73+
assert!(this.hir.tcx().is_thread_local_static(def_id));
74+
local_decl.internal = true;
75+
local_decl.local_info = Some(box LocalInfo::StaticRef { def_id, is_thread_local: true });
76+
}
77+
_ => {}
7078
}
7179
this.local_decls.push(local_decl)
7280
};

src/librustc_mir_build/build/expr/category.rs

+1
Original file line numberDiff line numberDiff line change
@@ -65,6 +65,7 @@ impl Category {
6565
| ExprKind::Repeat { .. }
6666
| ExprKind::Assign { .. }
6767
| ExprKind::AssignOp { .. }
68+
| ExprKind::ThreadLocalRef(_)
6869
| ExprKind::LlvmInlineAsm { .. } => Some(Category::Rvalue(RvalueFunc::AsRvalue)),
6970

7071
ExprKind::Literal { .. } | ExprKind::StaticRef { .. } => Some(Category::Constant),

src/librustc_mir_build/build/expr/into.rs

+1
Original file line numberDiff line numberDiff line change
@@ -445,6 +445,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
445445
| ExprKind::Tuple { .. }
446446
| ExprKind::Closure { .. }
447447
| ExprKind::Literal { .. }
448+
| ExprKind::ThreadLocalRef(_)
448449
| ExprKind::StaticRef { .. } => {
449450
debug_assert!(match Category::of(&expr.kind).unwrap() {
450451
// should be handled above

src/librustc_mir_build/hair/cx/expr.rs

+9-12
Original file line numberDiff line numberDiff line change
@@ -856,20 +856,17 @@ fn convert_path_expr<'a, 'tcx>(
856856
// a constant reference (or constant raw pointer for `static mut`) in MIR
857857
Res::Def(DefKind::Static, id) => {
858858
let ty = cx.tcx.static_ptr_ty(id);
859-
let ptr = cx.tcx.create_static_alloc(id);
860859
let temp_lifetime = cx.region_scope_tree.temporary_scope(expr.hir_id.local_id);
861-
ExprKind::Deref {
862-
arg: Expr {
863-
ty,
864-
temp_lifetime,
865-
span: expr.span,
866-
kind: ExprKind::StaticRef {
867-
literal: ty::Const::from_scalar(cx.tcx, Scalar::Ptr(ptr.into()), ty),
868-
def_id: id,
869-
},
860+
let kind = if cx.tcx.is_thread_local_static(id) {
861+
ExprKind::ThreadLocalRef(id)
862+
} else {
863+
let ptr = cx.tcx.create_static_alloc(id);
864+
ExprKind::StaticRef {
865+
literal: ty::Const::from_scalar(cx.tcx, Scalar::Ptr(ptr.into()), ty),
866+
def_id: id,
870867
}
871-
.to_ref(),
872-
}
868+
};
869+
ExprKind::Deref { arg: Expr { ty, temp_lifetime, span: expr.span, kind }.to_ref() }
873870
}
874871

875872
Res::Local(var_hir_id) => convert_var(cx, expr, var_hir_id),

src/librustc_mir_build/hair/mod.rs

+2
Original file line numberDiff line numberDiff line change
@@ -285,6 +285,8 @@ crate enum ExprKind<'tcx> {
285285
options: InlineAsmOptions,
286286
line_spans: &'tcx [Span],
287287
},
288+
/// An expression taking a reference to a thread local.
289+
ThreadLocalRef(DefId),
288290
LlvmInlineAsm {
289291
asm: &'tcx hir::LlvmInlineAsmInner,
290292
outputs: Vec<ExprRef<'tcx>>,

0 commit comments

Comments
 (0)