Skip to content

Commit 6e3cca5

Browse files
committed
Implement asm_const_ptr feature
The backend now fully supports codegen of const pointers, remove the block inside typeck behind a new feature gate. Tests are also added.
1 parent 28e3e81 commit 6e3cca5

12 files changed

Lines changed: 140 additions & 65 deletions

File tree

compiler/rustc_feature/src/unstable.rs

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -363,6 +363,8 @@ declare_features! (
363363
(unstable, arbitrary_self_types_pointers, "1.83.0", Some(44874)),
364364
/// Target features on arm.
365365
(unstable, arm_target_feature, "1.27.0", Some(150246)),
366+
/// Allows using `const` operands with pointer in inline assembly.
367+
(unstable, asm_const_ptr, "CURRENT_RUSTC_VERSION", Some(128464)),
366368
/// Enables experimental inline assembly support for additional architectures.
367369
(unstable, asm_experimental_arch, "1.58.0", Some(93335)),
368370
/// Enables experimental register support in inline assembly.

compiler/rustc_hir_typeck/src/errors.rs

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,13 @@ use rustc_span::{Ident, Span, Spanned, Symbol};
1818

1919
use crate::FnCtxt;
2020

21+
#[derive(Diagnostic)]
22+
#[diag("using pointers in asm `const` operand is experimental")]
23+
pub(crate) struct AsmConstPtrUnstable {
24+
#[primary_span]
25+
pub span: Span,
26+
}
27+
2128
#[derive(Diagnostic)]
2229
#[diag("base expression required after `..`", code = E0797)]
2330
pub(crate) struct BaseExpressionDoubleDot {

compiler/rustc_hir_typeck/src/inline_asm.rs

Lines changed: 33 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,7 @@ use rustc_target::asm::{
1515
use rustc_trait_selection::infer::InferCtxtExt;
1616

1717
use crate::FnCtxt;
18-
use crate::errors::RegisterTypeUnstable;
18+
use crate::errors::{AsmConstPtrUnstable, RegisterTypeUnstable};
1919

2020
pub(crate) struct InlineAsmCtxt<'a, 'tcx> {
2121
target_features: &'tcx FxIndexSet<Symbol>,
@@ -545,15 +545,46 @@ impl<'a, 'tcx> InlineAsmCtxt<'a, 'tcx> {
545545
match ty.kind() {
546546
ty::Error(_) => {}
547547
_ if ty.is_integral() => {}
548+
ty::FnPtr(..) => {
549+
if !self.tcx().features().asm_const_ptr() {
550+
self.tcx()
551+
.sess
552+
.create_feature_err(
553+
AsmConstPtrUnstable { span: op_sp },
554+
sym::asm_const_ptr,
555+
)
556+
.emit();
557+
}
558+
}
559+
ty::RawPtr(pointee, _) | ty::Ref(_, pointee, _)
560+
if self.is_thin_ptr_ty(op_sp, *pointee) =>
561+
{
562+
if !self.tcx().features().asm_const_ptr() {
563+
self.tcx()
564+
.sess
565+
.create_feature_err(
566+
AsmConstPtrUnstable { span: op_sp },
567+
sym::asm_const_ptr,
568+
)
569+
.emit();
570+
}
571+
}
548572
_ => {
573+
let const_possible_ty = if !self.tcx().features().asm_const_ptr() {
574+
"integer"
575+
} else {
576+
"integer or thin pointer"
577+
};
549578
self.fcx
550579
.dcx()
551580
.struct_span_err(op_sp, "invalid type for `const` operand")
552581
.with_span_label(
553582
self.tcx().def_span(anon_const.def_id),
554583
format!("is {} `{}`", ty.kind().article(), ty),
555584
)
556-
.with_help("`const` operands must be of an integer type")
585+
.with_help(format!(
586+
"`const` operands must be of an {const_possible_ty} type"
587+
))
557588
.emit();
558589
}
559590
}

compiler/rustc_span/src/symbol.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -417,6 +417,7 @@ symbols! {
417417
asm,
418418
asm_cfg,
419419
asm_const,
420+
asm_const_ptr,
420421
asm_experimental_arch,
421422
asm_experimental_reg,
422423
asm_goto,

tests/assembly-llvm/asm/global_asm.rs

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@
55
//@ compile-flags: -C symbol-mangling-version=v0
66

77
#![crate_type = "rlib"]
8+
#![feature(asm_const_ptr)]
89

910
use std::arch::global_asm;
1011

@@ -26,6 +27,10 @@ global_asm!("call {}", sym my_func);
2627
global_asm!("lea rax, [rip + {}]", sym MY_STATIC);
2728
// CHECK: call _RNvC[[CRATE_IDENT:[a-zA-Z0-9]{12}]]_10global_asm6foobar
2829
global_asm!("call {}", sym foobar);
30+
// CHECK: lea rax, [rip + _RNKNaC[[CRATE_IDENT]]_10global_asms4_00B3_]
31+
global_asm!("lea rax, [rip + {}]", const &1);
32+
// CHECK: lea rax, [rip + _RNKNaC[[CRATE_IDENT]]_10global_asms5_00B3_+4]
33+
global_asm!("lea rax, [rip + {}]", const &[1; 2][1]);
2934
// CHECK: _RNvC[[CRATE_IDENT]]_10global_asm6foobar:
3035
fn foobar() {
3136
loop {}

tests/assembly-llvm/asm/x86-types.rs

Lines changed: 10 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,7 @@
99
//@ compile-flags: -C target-feature=+avx512bw
1010
//@ compile-flags: -Zmerge-functions=disabled
1111

12-
#![feature(no_core, repr_simd, f16, f128)]
12+
#![feature(no_core, repr_simd, f16, f128, asm_const_ptr)]
1313
#![crate_type = "rlib"]
1414
#![no_core]
1515
#![allow(asm_sub_register, non_camel_case_types)]
@@ -101,6 +101,15 @@ pub unsafe fn sym_static() {
101101
asm!("mov al, byte ptr [{}]", sym extern_static);
102102
}
103103

104+
// CHECK-LABEL: const_ptr:
105+
// CHECK: #APP
106+
// CHECK: mov al, byte ptr [{{.*}}anon{{.*}}]
107+
// CHECK: #NO_APP
108+
#[no_mangle]
109+
pub unsafe fn const_ptr() {
110+
asm!("mov al, byte ptr [{}]", const &1u8);
111+
}
112+
104113
macro_rules! check {
105114
($func:ident $ty:ident $class:ident $mov:literal) => {
106115
#[no_mangle]
Lines changed: 5 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,19 +1,20 @@
11
//@ needs-asm-support
22
//@ ignore-nvptx64
33
//@ ignore-spirv
4+
//@ build-pass
5+
6+
#![feature(asm_const_ptr)]
47

58
use std::arch::{asm, global_asm};
69
use std::ptr::addr_of;
710

811
static FOO: u8 = 42;
912

10-
global_asm!("{}", const addr_of!(FOO));
11-
//~^ ERROR invalid type for `const` operand
13+
global_asm!("/* {} */", const addr_of!(FOO));
1214

1315
#[no_mangle]
1416
fn inline() {
15-
unsafe { asm!("{}", const addr_of!(FOO)) };
16-
//~^ ERROR invalid type for `const` operand
17+
unsafe { asm!("/* {} */", const addr_of!(FOO)) };
1718
}
1819

1920
fn main() {}

tests/ui/asm/const-refs-to-static.stderr

Lines changed: 0 additions & 22 deletions
This file was deleted.

tests/ui/asm/invalid-const-operand.rs

Lines changed: 9 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,8 @@
33
//@ ignore-spirv
44
//@ reference: asm.operand-type.supported-operands.const
55

6+
#![feature(asm_const_ptr)]
7+
68
use std::arch::{asm, global_asm};
79

810
// Const operands must be integers and must be constants.
@@ -13,21 +15,25 @@ global_asm!("{}", const 0i128);
1315
global_asm!("{}", const 0f32);
1416
//~^ ERROR invalid type for `const` operand
1517
global_asm!("{}", const 0 as *mut u8);
16-
//~^ ERROR invalid type for `const` operand
1718

1819
fn test1() {
1920
unsafe {
20-
// Const operands must be integers and must be constants.
21+
// Const operands must be integers or thin pointers
2122

2223
asm!("{}", const 0);
2324
asm!("{}", const 0i32);
2425
asm!("{}", const 0i128);
2526
asm!("{}", const 0f32);
2627
//~^ ERROR invalid type for `const` operand
2728
asm!("{}", const 0 as *mut u8);
28-
//~^ ERROR invalid type for `const` operand
2929
asm!("{}", const &0);
30+
asm!("{}", const b"Foo".as_slice());
3031
//~^ ERROR invalid type for `const` operand
32+
33+
asm!("{}", const test1 as fn());
34+
asm!("{}", const test1);
35+
asm!("{}", const (|| {}) as fn());
36+
asm!("{}", const || {});
3137
}
3238
}
3339

Lines changed: 13 additions & 33 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
error[E0435]: attempt to use a non-constant value in a constant
2-
--> $DIR/invalid-const-operand.rs:45:26
2+
--> $DIR/invalid-const-operand.rs:51:26
33
|
44
LL | asm!("{}", const x);
55
| ^ non-constant value
@@ -11,7 +11,7 @@ LL + const x: /* Type */ = 0;
1111
|
1212

1313
error[E0435]: attempt to use a non-constant value in a constant
14-
--> $DIR/invalid-const-operand.rs:48:36
14+
--> $DIR/invalid-const-operand.rs:54:36
1515
|
1616
LL | asm!("{}", const const_foo(x));
1717
| ^ non-constant value
@@ -23,7 +23,7 @@ LL + const x: /* Type */ = 0;
2323
|
2424

2525
error[E0435]: attempt to use a non-constant value in a constant
26-
--> $DIR/invalid-const-operand.rs:51:36
26+
--> $DIR/invalid-const-operand.rs:57:36
2727
|
2828
LL | asm!("{}", const const_bar(x));
2929
| ^ non-constant value
@@ -35,55 +35,35 @@ LL + const x: /* Type */ = 0;
3535
|
3636

3737
error: invalid type for `const` operand
38-
--> $DIR/invalid-const-operand.rs:13:19
38+
--> $DIR/invalid-const-operand.rs:15:19
3939
|
4040
LL | global_asm!("{}", const 0f32);
4141
| ^^^^^^----
4242
| |
4343
| is an `f32`
4444
|
45-
= help: `const` operands must be of an integer type
46-
47-
error: invalid type for `const` operand
48-
--> $DIR/invalid-const-operand.rs:15:19
49-
|
50-
LL | global_asm!("{}", const 0 as *mut u8);
51-
| ^^^^^^------------
52-
| |
53-
| is a `*mut u8`
54-
|
55-
= help: `const` operands must be of an integer type
45+
= help: `const` operands must be of an integer or thin pointer type
5646

5747
error: invalid type for `const` operand
58-
--> $DIR/invalid-const-operand.rs:25:20
48+
--> $DIR/invalid-const-operand.rs:26:20
5949
|
6050
LL | asm!("{}", const 0f32);
6151
| ^^^^^^----
6252
| |
6353
| is an `f32`
6454
|
65-
= help: `const` operands must be of an integer type
66-
67-
error: invalid type for `const` operand
68-
--> $DIR/invalid-const-operand.rs:27:20
69-
|
70-
LL | asm!("{}", const 0 as *mut u8);
71-
| ^^^^^^------------
72-
| |
73-
| is a `*mut u8`
74-
|
75-
= help: `const` operands must be of an integer type
55+
= help: `const` operands must be of an integer or thin pointer type
7656

7757
error: invalid type for `const` operand
78-
--> $DIR/invalid-const-operand.rs:29:20
58+
--> $DIR/invalid-const-operand.rs:30:20
7959
|
80-
LL | asm!("{}", const &0);
81-
| ^^^^^^--
60+
LL | asm!("{}", const b"Foo".as_slice());
61+
| ^^^^^^-----------------
8262
| |
83-
| is a `&i32`
63+
| is a `&[u8]`
8464
|
85-
= help: `const` operands must be of an integer type
65+
= help: `const` operands must be of an integer or thin pointer type
8666

87-
error: aborting due to 8 previous errors
67+
error: aborting due to 6 previous errors
8868

8969
For more information about this error, try `rustc --explain E0435`.

0 commit comments

Comments
 (0)