1
Fork 0

Add support for BPF inline assembly

This commit is contained in:
Alessandro Decina 2021-04-20 19:03:10 +10:00
parent 12ac719b99
commit b2a6967114
10 changed files with 176 additions and 3 deletions

View file

@ -288,6 +288,7 @@ impl AsmBuilderMethods<'tcx> for Builder<'a, 'll, 'tcx> {
InlineAsmArch::Mips | InlineAsmArch::Mips64 => {} InlineAsmArch::Mips | InlineAsmArch::Mips64 => {}
InlineAsmArch::SpirV => {} InlineAsmArch::SpirV => {}
InlineAsmArch::Wasm32 => {} InlineAsmArch::Wasm32 => {}
InlineAsmArch::Bpf => {}
} }
} }
if !options.contains(InlineAsmOptions::NOMEM) { if !options.contains(InlineAsmOptions::NOMEM) {
@ -593,6 +594,8 @@ fn reg_to_llvm(reg: InlineAsmRegOrRegClass, layout: Option<&TyAndLayout<'tcx>>)
InlineAsmRegClass::X86(X86InlineAsmRegClass::zmm_reg) => "v", InlineAsmRegClass::X86(X86InlineAsmRegClass::zmm_reg) => "v",
InlineAsmRegClass::X86(X86InlineAsmRegClass::kreg) => "^Yk", InlineAsmRegClass::X86(X86InlineAsmRegClass::kreg) => "^Yk",
InlineAsmRegClass::Wasm(WasmInlineAsmRegClass::local) => "r", InlineAsmRegClass::Wasm(WasmInlineAsmRegClass::local) => "r",
InlineAsmRegClass::Bpf(BpfInlineAsmRegClass::reg) => "r",
InlineAsmRegClass::Bpf(BpfInlineAsmRegClass::wreg) => "w",
InlineAsmRegClass::SpirV(SpirVInlineAsmRegClass::reg) => { InlineAsmRegClass::SpirV(SpirVInlineAsmRegClass::reg) => {
bug!("LLVM backend does not support SPIR-V") bug!("LLVM backend does not support SPIR-V")
} }
@ -661,6 +664,7 @@ fn modifier_to_llvm(
}, },
InlineAsmRegClass::X86(X86InlineAsmRegClass::kreg) => None, InlineAsmRegClass::X86(X86InlineAsmRegClass::kreg) => None,
InlineAsmRegClass::Wasm(WasmInlineAsmRegClass::local) => None, InlineAsmRegClass::Wasm(WasmInlineAsmRegClass::local) => None,
InlineAsmRegClass::Bpf(_) => None,
InlineAsmRegClass::SpirV(SpirVInlineAsmRegClass::reg) => { InlineAsmRegClass::SpirV(SpirVInlineAsmRegClass::reg) => {
bug!("LLVM backend does not support SPIR-V") bug!("LLVM backend does not support SPIR-V")
} }
@ -708,6 +712,8 @@ fn dummy_output_type(cx: &CodegenCx<'ll, 'tcx>, reg: InlineAsmRegClass) -> &'ll
| InlineAsmRegClass::X86(X86InlineAsmRegClass::zmm_reg) => cx.type_f32(), | InlineAsmRegClass::X86(X86InlineAsmRegClass::zmm_reg) => cx.type_f32(),
InlineAsmRegClass::X86(X86InlineAsmRegClass::kreg) => cx.type_i16(), InlineAsmRegClass::X86(X86InlineAsmRegClass::kreg) => cx.type_i16(),
InlineAsmRegClass::Wasm(WasmInlineAsmRegClass::local) => cx.type_i32(), InlineAsmRegClass::Wasm(WasmInlineAsmRegClass::local) => cx.type_i32(),
InlineAsmRegClass::Bpf(BpfInlineAsmRegClass::reg) => cx.type_i64(),
InlineAsmRegClass::Bpf(BpfInlineAsmRegClass::wreg) => cx.type_i32(),
InlineAsmRegClass::SpirV(SpirVInlineAsmRegClass::reg) => { InlineAsmRegClass::SpirV(SpirVInlineAsmRegClass::reg) => {
bug!("LLVM backend does not support SPIR-V") bug!("LLVM backend does not support SPIR-V")
} }

View file

@ -210,6 +210,8 @@ const WASM_ALLOWED_FEATURES: &[(&str, Option<Symbol>)] = &[
("nontrapping-fptoint", Some(sym::wasm_target_feature)), ("nontrapping-fptoint", Some(sym::wasm_target_feature)),
]; ];
const BPF_ALLOWED_FEATURES: &[(&str, Option<Symbol>)] = &[("alu32", Some(sym::bpf_target_feature))];
/// When rustdoc is running, provide a list of all known features so that all their respective /// When rustdoc is running, provide a list of all known features so that all their respective
/// primitives may be documented. /// primitives may be documented.
/// ///
@ -224,6 +226,7 @@ pub fn all_known_features() -> impl Iterator<Item = (&'static str, Option<Symbol
.chain(MIPS_ALLOWED_FEATURES.iter()) .chain(MIPS_ALLOWED_FEATURES.iter())
.chain(RISCV_ALLOWED_FEATURES.iter()) .chain(RISCV_ALLOWED_FEATURES.iter())
.chain(WASM_ALLOWED_FEATURES.iter()) .chain(WASM_ALLOWED_FEATURES.iter())
.chain(BPF_ALLOWED_FEATURES.iter())
.cloned() .cloned()
} }
@ -237,6 +240,7 @@ pub fn supported_target_features(sess: &Session) -> &'static [(&'static str, Opt
"powerpc" | "powerpc64" => POWERPC_ALLOWED_FEATURES, "powerpc" | "powerpc64" => POWERPC_ALLOWED_FEATURES,
"riscv32" | "riscv64" => RISCV_ALLOWED_FEATURES, "riscv32" | "riscv64" => RISCV_ALLOWED_FEATURES,
"wasm32" | "wasm64" => WASM_ALLOWED_FEATURES, "wasm32" | "wasm64" => WASM_ALLOWED_FEATURES,
"bpf" => BPF_ALLOWED_FEATURES,
_ => &[], _ => &[],
} }
} }

View file

@ -328,6 +328,7 @@ symbols! {
box_free, box_free,
box_patterns, box_patterns,
box_syntax, box_syntax,
bpf_target_feature,
braced_empty_structs, braced_empty_structs,
branch, branch,
breakpoint, breakpoint,
@ -1332,6 +1333,7 @@ symbols! {
wrapping_add, wrapping_add,
wrapping_mul, wrapping_mul,
wrapping_sub, wrapping_sub,
wreg,
write_bytes, write_bytes,
xmm_reg, xmm_reg,
ymm_reg, ymm_reg,

View file

@ -655,7 +655,7 @@ impl<'a, Ty> FnAbi<'a, Ty> {
} }
} }
"asmjs" => wasm::compute_c_abi_info(cx, self), "asmjs" => wasm::compute_c_abi_info(cx, self),
"bpfel" | "bpfeb" => bpf::compute_abi_info(self), "bpf" => bpf::compute_abi_info(self),
a => return Err(format!("unrecognized arch \"{}\" in target specification", a)), a => return Err(format!("unrecognized arch \"{}\" in target specification", a)),
} }

View file

@ -0,0 +1,129 @@
use super::{InlineAsmArch, InlineAsmType, Target};
use rustc_macros::HashStable_Generic;
use std::fmt;
def_reg_class! {
Bpf BpfInlineAsmRegClass {
reg,
wreg,
}
}
impl BpfInlineAsmRegClass {
pub fn valid_modifiers(self, _arch: InlineAsmArch) -> &'static [char] {
&[]
}
pub fn suggest_class(self, _arch: InlineAsmArch, _ty: InlineAsmType) -> Option<Self> {
None
}
pub fn suggest_modifier(
self,
_arch: InlineAsmArch,
_ty: InlineAsmType,
) -> Option<(char, &'static str)> {
None
}
pub fn default_modifier(self, _arch: InlineAsmArch) -> Option<(char, &'static str)> {
None
}
pub fn supported_types(
self,
_arch: InlineAsmArch,
) -> &'static [(InlineAsmType, Option<&'static str>)] {
match self {
Self::reg => types! { _: I8, I16, I32, I64; },
Self::wreg => types! { "alu32": I8, I16, I32; },
}
}
}
fn only_alu32(
_arch: InlineAsmArch,
mut has_feature: impl FnMut(&str) -> bool,
_target: &Target,
) -> Result<(), &'static str> {
if !has_feature("alu32") {
Err("register can't be used without the `alu32` target feature")
} else {
Ok(())
}
}
def_regs! {
Bpf BpfInlineAsmReg BpfInlineAsmRegClass {
r0: reg = ["r0"],
r1: reg = ["r1"],
r2: reg = ["r2"],
r3: reg = ["r3"],
r4: reg = ["r4"],
r5: reg = ["r5"],
r6: reg = ["r6"],
r7: reg = ["r7"],
r8: reg = ["r8"],
r9: reg = ["r9"],
w0: wreg = ["w0"] % only_alu32,
w1: wreg = ["w1"] % only_alu32,
w2: wreg = ["w2"] % only_alu32,
w3: wreg = ["w3"] % only_alu32,
w4: wreg = ["w4"] % only_alu32,
w5: wreg = ["w5"] % only_alu32,
w6: wreg = ["w6"] % only_alu32,
w7: wreg = ["w7"] % only_alu32,
w8: wreg = ["w8"] % only_alu32,
w9: wreg = ["w9"] % only_alu32,
#error = ["r10", "w10"] =>
"the stack pointer cannot be used as an operand for inline asm",
}
}
impl BpfInlineAsmReg {
pub fn emit(
self,
out: &mut dyn fmt::Write,
_arch: InlineAsmArch,
_modifier: Option<char>,
) -> fmt::Result {
out.write_str(self.name())
}
pub fn overlapping_regs(self, mut cb: impl FnMut(BpfInlineAsmReg)) {
cb(self);
macro_rules! reg_conflicts {
(
$(
$r:ident : $w:ident
),*
) => {
match self {
$(
Self::$r => {
cb(Self::$w);
}
Self::$w => {
cb(Self::$r);
}
)*
}
};
}
reg_conflicts! {
r0 : w0,
r1 : w1,
r2 : w2,
r3 : w3,
r4 : w4,
r5 : w5,
r6 : w6,
r7 : w7,
r8 : w8,
r9 : w9
}
}
}

View file

@ -148,6 +148,7 @@ macro_rules! types {
mod aarch64; mod aarch64;
mod arm; mod arm;
mod bpf;
mod hexagon; mod hexagon;
mod mips; mod mips;
mod nvptx; mod nvptx;
@ -159,6 +160,7 @@ mod x86;
pub use aarch64::{AArch64InlineAsmReg, AArch64InlineAsmRegClass}; pub use aarch64::{AArch64InlineAsmReg, AArch64InlineAsmRegClass};
pub use arm::{ArmInlineAsmReg, ArmInlineAsmRegClass}; pub use arm::{ArmInlineAsmReg, ArmInlineAsmRegClass};
pub use bpf::{BpfInlineAsmReg, BpfInlineAsmRegClass};
pub use hexagon::{HexagonInlineAsmReg, HexagonInlineAsmRegClass}; pub use hexagon::{HexagonInlineAsmReg, HexagonInlineAsmRegClass};
pub use mips::{MipsInlineAsmReg, MipsInlineAsmRegClass}; pub use mips::{MipsInlineAsmReg, MipsInlineAsmRegClass};
pub use nvptx::{NvptxInlineAsmReg, NvptxInlineAsmRegClass}; pub use nvptx::{NvptxInlineAsmReg, NvptxInlineAsmRegClass};
@ -184,6 +186,7 @@ pub enum InlineAsmArch {
PowerPC64, PowerPC64,
SpirV, SpirV,
Wasm32, Wasm32,
Bpf,
} }
impl FromStr for InlineAsmArch { impl FromStr for InlineAsmArch {
@ -205,6 +208,7 @@ impl FromStr for InlineAsmArch {
"mips64" => Ok(Self::Mips64), "mips64" => Ok(Self::Mips64),
"spirv" => Ok(Self::SpirV), "spirv" => Ok(Self::SpirV),
"wasm32" => Ok(Self::Wasm32), "wasm32" => Ok(Self::Wasm32),
"bpf" => Ok(Self::Bpf),
_ => Err(()), _ => Err(()),
} }
} }
@ -233,6 +237,7 @@ pub enum InlineAsmReg {
Mips(MipsInlineAsmReg), Mips(MipsInlineAsmReg),
SpirV(SpirVInlineAsmReg), SpirV(SpirVInlineAsmReg),
Wasm(WasmInlineAsmReg), Wasm(WasmInlineAsmReg),
Bpf(BpfInlineAsmReg),
// Placeholder for invalid register constraints for the current target // Placeholder for invalid register constraints for the current target
Err, Err,
} }
@ -247,6 +252,7 @@ impl InlineAsmReg {
Self::PowerPC(r) => r.name(), Self::PowerPC(r) => r.name(),
Self::Hexagon(r) => r.name(), Self::Hexagon(r) => r.name(),
Self::Mips(r) => r.name(), Self::Mips(r) => r.name(),
Self::Bpf(r) => r.name(),
Self::Err => "<reg>", Self::Err => "<reg>",
} }
} }
@ -260,6 +266,7 @@ impl InlineAsmReg {
Self::PowerPC(r) => InlineAsmRegClass::PowerPC(r.reg_class()), Self::PowerPC(r) => InlineAsmRegClass::PowerPC(r.reg_class()),
Self::Hexagon(r) => InlineAsmRegClass::Hexagon(r.reg_class()), Self::Hexagon(r) => InlineAsmRegClass::Hexagon(r.reg_class()),
Self::Mips(r) => InlineAsmRegClass::Mips(r.reg_class()), Self::Mips(r) => InlineAsmRegClass::Mips(r.reg_class()),
Self::Bpf(r) => InlineAsmRegClass::Bpf(r.reg_class()),
Self::Err => InlineAsmRegClass::Err, Self::Err => InlineAsmRegClass::Err,
} }
} }
@ -304,6 +311,9 @@ impl InlineAsmReg {
InlineAsmArch::Wasm32 => { InlineAsmArch::Wasm32 => {
Self::Wasm(WasmInlineAsmReg::parse(arch, has_feature, target, &name)?) Self::Wasm(WasmInlineAsmReg::parse(arch, has_feature, target, &name)?)
} }
InlineAsmArch::Bpf => {
Self::Bpf(BpfInlineAsmReg::parse(arch, has_feature, target, &name)?)
}
}) })
} }
@ -323,6 +333,7 @@ impl InlineAsmReg {
Self::PowerPC(r) => r.emit(out, arch, modifier), Self::PowerPC(r) => r.emit(out, arch, modifier),
Self::Hexagon(r) => r.emit(out, arch, modifier), Self::Hexagon(r) => r.emit(out, arch, modifier),
Self::Mips(r) => r.emit(out, arch, modifier), Self::Mips(r) => r.emit(out, arch, modifier),
Self::Bpf(r) => r.emit(out, arch, modifier),
Self::Err => unreachable!("Use of InlineAsmReg::Err"), Self::Err => unreachable!("Use of InlineAsmReg::Err"),
} }
} }
@ -336,6 +347,7 @@ impl InlineAsmReg {
Self::PowerPC(_) => cb(self), Self::PowerPC(_) => cb(self),
Self::Hexagon(r) => r.overlapping_regs(|r| cb(Self::Hexagon(r))), Self::Hexagon(r) => r.overlapping_regs(|r| cb(Self::Hexagon(r))),
Self::Mips(_) => cb(self), Self::Mips(_) => cb(self),
Self::Bpf(r) => r.overlapping_regs(|r| cb(Self::Bpf(r))),
Self::Err => unreachable!("Use of InlineAsmReg::Err"), Self::Err => unreachable!("Use of InlineAsmReg::Err"),
} }
} }
@ -364,6 +376,7 @@ pub enum InlineAsmRegClass {
Mips(MipsInlineAsmRegClass), Mips(MipsInlineAsmRegClass),
SpirV(SpirVInlineAsmRegClass), SpirV(SpirVInlineAsmRegClass),
Wasm(WasmInlineAsmRegClass), Wasm(WasmInlineAsmRegClass),
Bpf(BpfInlineAsmRegClass),
// Placeholder for invalid register constraints for the current target // Placeholder for invalid register constraints for the current target
Err, Err,
} }
@ -381,6 +394,7 @@ impl InlineAsmRegClass {
Self::Mips(r) => r.name(), Self::Mips(r) => r.name(),
Self::SpirV(r) => r.name(), Self::SpirV(r) => r.name(),
Self::Wasm(r) => r.name(), Self::Wasm(r) => r.name(),
Self::Bpf(r) => r.name(),
Self::Err => rustc_span::symbol::sym::reg, Self::Err => rustc_span::symbol::sym::reg,
} }
} }
@ -400,6 +414,7 @@ impl InlineAsmRegClass {
Self::Mips(r) => r.suggest_class(arch, ty).map(InlineAsmRegClass::Mips), Self::Mips(r) => r.suggest_class(arch, ty).map(InlineAsmRegClass::Mips),
Self::SpirV(r) => r.suggest_class(arch, ty).map(InlineAsmRegClass::SpirV), Self::SpirV(r) => r.suggest_class(arch, ty).map(InlineAsmRegClass::SpirV),
Self::Wasm(r) => r.suggest_class(arch, ty).map(InlineAsmRegClass::Wasm), Self::Wasm(r) => r.suggest_class(arch, ty).map(InlineAsmRegClass::Wasm),
Self::Bpf(r) => r.suggest_class(arch, ty).map(InlineAsmRegClass::Bpf),
Self::Err => unreachable!("Use of InlineAsmRegClass::Err"), Self::Err => unreachable!("Use of InlineAsmRegClass::Err"),
} }
} }
@ -426,6 +441,7 @@ impl InlineAsmRegClass {
Self::Mips(r) => r.suggest_modifier(arch, ty), Self::Mips(r) => r.suggest_modifier(arch, ty),
Self::SpirV(r) => r.suggest_modifier(arch, ty), Self::SpirV(r) => r.suggest_modifier(arch, ty),
Self::Wasm(r) => r.suggest_modifier(arch, ty), Self::Wasm(r) => r.suggest_modifier(arch, ty),
Self::Bpf(r) => r.suggest_modifier(arch, ty),
Self::Err => unreachable!("Use of InlineAsmRegClass::Err"), Self::Err => unreachable!("Use of InlineAsmRegClass::Err"),
} }
} }
@ -448,6 +464,7 @@ impl InlineAsmRegClass {
Self::Mips(r) => r.default_modifier(arch), Self::Mips(r) => r.default_modifier(arch),
Self::SpirV(r) => r.default_modifier(arch), Self::SpirV(r) => r.default_modifier(arch),
Self::Wasm(r) => r.default_modifier(arch), Self::Wasm(r) => r.default_modifier(arch),
Self::Bpf(r) => r.default_modifier(arch),
Self::Err => unreachable!("Use of InlineAsmRegClass::Err"), Self::Err => unreachable!("Use of InlineAsmRegClass::Err"),
} }
} }
@ -469,6 +486,7 @@ impl InlineAsmRegClass {
Self::Mips(r) => r.supported_types(arch), Self::Mips(r) => r.supported_types(arch),
Self::SpirV(r) => r.supported_types(arch), Self::SpirV(r) => r.supported_types(arch),
Self::Wasm(r) => r.supported_types(arch), Self::Wasm(r) => r.supported_types(arch),
Self::Bpf(r) => r.supported_types(arch),
Self::Err => unreachable!("Use of InlineAsmRegClass::Err"), Self::Err => unreachable!("Use of InlineAsmRegClass::Err"),
} }
} }
@ -493,6 +511,7 @@ impl InlineAsmRegClass {
} }
InlineAsmArch::SpirV => Self::SpirV(SpirVInlineAsmRegClass::parse(arch, name)?), InlineAsmArch::SpirV => Self::SpirV(SpirVInlineAsmRegClass::parse(arch, name)?),
InlineAsmArch::Wasm32 => Self::Wasm(WasmInlineAsmRegClass::parse(arch, name)?), InlineAsmArch::Wasm32 => Self::Wasm(WasmInlineAsmRegClass::parse(arch, name)?),
InlineAsmArch::Bpf => Self::Bpf(BpfInlineAsmRegClass::parse(arch, name)?),
}) })
} }
@ -510,6 +529,7 @@ impl InlineAsmRegClass {
Self::Mips(r) => r.valid_modifiers(arch), Self::Mips(r) => r.valid_modifiers(arch),
Self::SpirV(r) => r.valid_modifiers(arch), Self::SpirV(r) => r.valid_modifiers(arch),
Self::Wasm(r) => r.valid_modifiers(arch), Self::Wasm(r) => r.valid_modifiers(arch),
Self::Bpf(r) => r.valid_modifiers(arch),
Self::Err => unreachable!("Use of InlineAsmRegClass::Err"), Self::Err => unreachable!("Use of InlineAsmRegClass::Err"),
} }
} }
@ -679,5 +699,10 @@ pub fn allocatable_registers(
wasm::fill_reg_map(arch, has_feature, target, &mut map); wasm::fill_reg_map(arch, has_feature, target, &mut map);
map map
} }
InlineAsmArch::Bpf => {
let mut map = bpf::regclass_map();
bpf::fill_reg_map(arch, has_feature, target, &mut map);
map
}
} }
} }

View file

@ -3,6 +3,7 @@ use crate::{abi::Endian, spec::abi::Abi};
pub fn opts(endian: Endian) -> TargetOptions { pub fn opts(endian: Endian) -> TargetOptions {
TargetOptions { TargetOptions {
allow_asm: true,
endian, endian,
linker_flavor: LinkerFlavor::BpfLinker, linker_flavor: LinkerFlavor::BpfLinker,
atomic_cas: false, atomic_cas: false,

View file

@ -6,7 +6,7 @@ pub fn target() -> Target {
llvm_target: "bpfeb".to_string(), llvm_target: "bpfeb".to_string(),
data_layout: "E-m:e-p:64:64-i64:64-i128:128-n32:64-S128".to_string(), data_layout: "E-m:e-p:64:64-i64:64-i128:128-n32:64-S128".to_string(),
pointer_width: 64, pointer_width: 64,
arch: "bpfeb".to_string(), arch: "bpf".to_string(),
options: bpf_base::opts(Endian::Big), options: bpf_base::opts(Endian::Big),
} }
} }

View file

@ -6,7 +6,7 @@ pub fn target() -> Target {
llvm_target: "bpfel".to_string(), llvm_target: "bpfel".to_string(),
data_layout: "e-m:e-p:64:64-i64:64-i128:128-n32:64-S128".to_string(), data_layout: "e-m:e-p:64:64-i64:64-i128:128-n32:64-S128".to_string(),
pointer_width: 64, pointer_width: 64,
arch: "bpfel".to_string(), arch: "bpf".to_string(),
options: bpf_base::opts(Endian::Little), options: bpf_base::opts(Endian::Little),
} }
} }

View file

@ -30,6 +30,7 @@ Inline assembly is currently supported on the following architectures:
- Hexagon - Hexagon
- MIPS32r2 and MIPS64r2 - MIPS32r2 and MIPS64r2
- wasm32 - wasm32
- BPF
## Basic usage ## Basic usage
@ -570,6 +571,8 @@ Here is the list of currently supported register classes:
| PowerPC | `reg_nonzero` | | `r[1-31]` | `b` | | PowerPC | `reg_nonzero` | | `r[1-31]` | `b` |
| PowerPC | `freg` | `f[0-31]` | `f` | | PowerPC | `freg` | `f[0-31]` | `f` |
| wasm32 | `local` | None\* | `r` | | wasm32 | `local` | None\* | `r` |
| BPF | `reg` | `r[0-10]` | `r`|
| BPF | `wreg` | `w[0-10]` | `w`|
> **Note**: On x86 we treat `reg_byte` differently from `reg` because the compiler can allocate `al` and `ah` separately whereas `reg` reserves the whole register. > **Note**: On x86 we treat `reg_byte` differently from `reg` because the compiler can allocate `al` and `ah` separately whereas `reg` reserves the whole register.
> >
@ -615,6 +618,8 @@ Each register class has constraints on which value types they can be used with.
| PowerPC | `reg_nonzero` | None | `i8`, `i16`, `i32` | | PowerPC | `reg_nonzero` | None | `i8`, `i16`, `i32` |
| PowerPC | `freg` | None | `f32`, `f64` | | PowerPC | `freg` | None | `f32`, `f64` |
| wasm32 | `local` | None | `i8` `i16` `i32` `i64` `f32` `f64` | | wasm32 | `local` | None | `i8` `i16` `i32` `i64` `f32` `f64` |
| BPF | `reg` | None | `i8` `i16` `i32` `i64` |
| BPF | `wreg` | `alu32` | `i8` `i16` `i32`|
> **Note**: For the purposes of the above table pointers, function pointers and `isize`/`usize` are treated as the equivalent integer type (`i16`/`i32`/`i64` depending on the target). > **Note**: For the purposes of the above table pointers, function pointers and `isize`/`usize` are treated as the equivalent integer type (`i16`/`i32`/`i64` depending on the target).
@ -674,6 +679,7 @@ Some registers have multiple names. These are all treated by the compiler as ide
| Hexagon | `r29` | `sp` | | Hexagon | `r29` | `sp` |
| Hexagon | `r30` | `fr` | | Hexagon | `r30` | `fr` |
| Hexagon | `r31` | `lr` | | Hexagon | `r31` | `lr` |
| BPF | `r[0-10]` | `w[0-10]` |
Some registers cannot be used for input or output operands: Some registers cannot be used for input or output operands: