小编Luk*_*odt的帖子

为什么空函数不会作为LLVM IR中的死代码删除?

从这个简单的C程序开始:

void nothing(void) {}
int main() {
  int i;
  for (i = 0; i < 10; ++i) {
    nothing();
  }
  return 0;
}
Run Code Online (Sandbox Code Playgroud)

我的传递输出如下:
注意:IR语句为绿色.

; Function Attrs: nounwind readnone ssp uwtable
define void @nothing() #0 {
entry:
  ret void
}

; Function Attrs: nounwind readnone ssp uwtable
define i32 @main() #0 {
entry:
  ret i32 0
}
Run Code Online (Sandbox Code Playgroud)

IR

问:使用O3其认为是最高级别的优化,为什么没有nothing功能尚未消除的死代码?

c clang llvm-clang llvm-ir llvm-codegen

10
推荐指数
1
解决办法
579
查看次数

有哪些类型的宏/语法扩展/编译器插件?

我很困惑Rust生态系统中用于几个宏观事物的许多术语.有人可以澄清一下哪些宏/语法扩展/编译器插件以及解释这些术语之间的关系?

macros rust

10
推荐指数
1
解决办法
480
查看次数

这个错误是由于编译器对RefCell的特殊了解吗?

fn works<'a>(foo: &Option<&'a mut String>, s: &'a mut String) {}
fn error<'a>(foo: &RefCell<Option<&'a mut String>>, s: &'a mut String) {}

let mut s = "hi".to_string();

let foo = None;
works(&foo, &mut s);

// with this, it errors
// let bar = RefCell::new(None);
// error(&bar, &mut s);

s.len();
Run Code Online (Sandbox Code Playgroud)

如果我在注释中添加两行,则会发生以下错误:

error[E0502]: cannot borrow `s` as immutable because it is also borrowed as mutable
  --> <anon>:16:5
   |
14 |     error(&bar, &mut s);
   |                      - mutable borrow occurs here
15 |     
16 |     s.len(); …
Run Code Online (Sandbox Code Playgroud)

rust borrow-checker

10
推荐指数
1
解决办法
140
查看次数

我可以强制Rust不优化单个函数吗?

我有一个功能,Rust的/ LLVM的优化失败并导致恐慌(在发布版本中),而未优化的代码(调试版本)工作正常.如果我比较生成的汇编代码,我甚至无法理解优化器试图完成的任务.(原因可能是这个函数使用内联汇编程序.)

有没有办法告诉Rust在优化过程中单独保留某些功能,还是必须关闭所有优化?

这是具体功能:

#[naked]
pub extern "C" fn dispatch_svc(){
    Cpu::save_context();
    let mut nr: u32 = 0;
    unsafe {
        asm!("ldr r0, [lr, #-4]
              bic $0, r0, #0xff000000":"=r"(nr)::"r0":"volatile")
    };
    swi_service_routine(nr);
    Cpu::restore_context_and_return();
}
Run Code Online (Sandbox Code Playgroud)

optimization rust llvm-codegen

10
推荐指数
2
解决办法
1395
查看次数

为什么Rust编译器不能优化Box :: downcast的Err arm?

我有一个Box<dyn Any>,我知道基础类型,所以我想在Box::downcast()()中优化测试.

首先我试过std::hint::unreachable_unchecked():

pub unsafe fn downcast() -> Box<i32> {
    let value = any();
    if let Ok(value) = value.downcast() {
        value
    } else {
        std::hint::unreachable_unchecked()
    }
}
Run Code Online (Sandbox Code Playgroud)

pub unsafe fn downcast() -> Box<i32> {
    any().downcast().map_err(|_| std::hint::unreachable_unchecked()).unwrap()
}
Run Code Online (Sandbox Code Playgroud)

rustc -C opt-level=3两个结果在该(40行中省略):

example::downcast:
        push    rbx
        sub     rsp, 16
        call    any@PLT
        mov     rbx, rax
        mov     qword ptr [rsp], rax
        mov     qword ptr [rsp + 8], rdx
        mov     rdi, rax
        call    qword ptr …
Run Code Online (Sandbox Code Playgroud)

optimization assembly compiler-optimization rust llvm-codegen

10
推荐指数
1
解决办法
279
查看次数

如何使用引用宏报告过程宏中的错误?

我正在编写一个程序宏,它工作正常,但我无法以符合人体工程学的方式报告错误.使用panic!"工作"但不优雅,并且不会很好地向用户显示错误消息.

我知道我可以在解析a时报告错误TokenStream,但是在解析之后我需要在遍历AST时产生错误.

宏调用如下所示:

attr_test! {
    #[bool]
    FOO
}
Run Code Online (Sandbox Code Playgroud)

并应输出:

const FOO: bool = false;
Run Code Online (Sandbox Code Playgroud)

这是宏代码:

extern crate proc_macro;
use quote::quote;
use syn::parse::{Parse, ParseStream, Result};
use syn::{Attribute, parse_macro_input, Ident, Meta};

struct AttrTest {
    attributes: Vec<Attribute>,
    name: Ident,
}

impl Parse for AttrTest {
    fn parse(input: ParseStream) -> Result<Self> {
        Ok(AttrTest {
            attributes: input.call(Attribute::parse_outer)?,
            name: input.parse()?,
        })
    }
}

#[proc_macro]
pub fn attr_test(tokens: proc_macro::TokenStream) -> proc_macro::TokenStream {
    let test: AttrTest = parse_macro_input!(tokens);
    let name = test.name;
    let first_att …
Run Code Online (Sandbox Code Playgroud)

error-handling rust rust-macros rust-proc-macros

10
推荐指数
2
解决办法
615
查看次数

编译器强迫我执行特征方法,但是我的类型从不满足方法上的`Self`特征

我有个特质Foo如果那些实现者实现了另一个特征(Clone在本示例中),我想强迫实现者定义一个方法。我的想法(游乐场):

trait Foo {
    // Note: in my real application, the trait has other methods as well,
    // so I can't simply add `Clone` as super trait
    fn foo(&self) 
    where 
        Self: Clone;
}

struct NoClone;
impl Foo for NoClone {}
Run Code Online (Sandbox Code Playgroud)

可悲的是,这导致:

error[E0046]: not all trait items implemented, missing: `foo`
 --> src/lib.rs:8:1
  |
2 | /     fn foo(&self) 
3 | |     where 
4 | |         Self: Clone;
  | |____________________- `foo` from trait
... …
Run Code Online (Sandbox Code Playgroud)

traits rust

10
推荐指数
1
解决办法
211
查看次数

使用函数指针时,"预期的fn项,找到了不同的fn项"

我有以下代码(游乐场):

// Two dummy functions, both with the signature `fn(u32) -> bool`
fn foo(x: u32) -> bool {
    x % 2 == 0
}
fn bar(x: u32) -> bool {
    x == 27
}


fn call_both<F>(a: F, b: F)
where
    F: Fn(u32) -> bool,
{
    a(5);
    b(5);
}

fn main() {
    call_both(foo, bar);  // <-- error
}
Run Code Online (Sandbox Code Playgroud)

对我来说,它看起来这应该是编译foobar具有相同的签名:fn(u32) -> bool.然而,我收到以下错误:

error[E0308]: mismatched types
  --> src/main.rs:20:20
   |
20 |     call_both(foo, bar);
   |                    ^^^ …
Run Code Online (Sandbox Code Playgroud)

rust

9
推荐指数
2
解决办法
990
查看次数

如何从单个元素创建切片而不复制该元素?

我有一个非常大的结构(在堆上和堆栈上),我在函数中使用。大多数时候,我想要该结构的一个简单变量,因为我直接对大结构进行操作。然而,在某一时刻,我被迫(通过函数签名)将此结构传递到切片内部。

struct VeryBig(Vec<String>, [u64; 50]);

fn takes_slice(_: &[VeryBig]) {}

fn main() {
    let foo = VeryBig(vec!["Ferris".to_string(); 100], [27; 50]);

    // Use `foo` directly a bunch of times

    takes_slice(&foo); // <-- mismatched type

    // Use `foo` directly a bunch of times
}
Run Code Online (Sandbox Code Playgroud)

这显然并且可以理解地导致了这个错误:

error[E0308]: mismatched types
  --> src/main.rs:10:17
   |
10 |     takes_slice(&foo); // <-- mismatched type
   |                 ^^^^ expected slice, found struct `VeryBig`
   |
   = note: expected type `&[VeryBig]`
              found type `&VeryBig`
Run Code Online (Sandbox Code Playgroud)

所以我想知道:解决这个问题的最佳方法是什么?我可以只制作foo一个[VeryBig; 1],但这意味着我必须在foo[0] …

slice rust

9
推荐指数
1
解决办法
3476
查看次数

如何安全地从`&mut [u32]`获取不可变的字节片?

在我的项目的相当低级的部分中,函数接收可变的原始数据切片(&mut [u32]在这种情况下)。此数据应以小端序写入作者。

现在,仅此一项就不成问题,但是所有这些必须快速。我评估了我的应用程序,并将其确定为关键路径之一。特别是,如果不需要更改字节序(因为我们已经在一个小的字节序系统上),那么就不会有任何开销。

这是我的代码(Playground):

use std::{io, mem, slice};

fn write_data(mut w: impl io::Write, data: &mut [u32]) -> Result<(), io::Error> {
    adjust_endianness(data);

    // Is this safe?
    let bytes = unsafe {
        let len = data.len() * mem::size_of::<u32>();
        let ptr = data.as_ptr() as *const u8;
        slice::from_raw_parts(ptr, len)
    };

    w.write_all(bytes)
}

fn adjust_endianness(_: &mut [u32]) {
    // implementation omitted
}
Run Code Online (Sandbox Code Playgroud)

adjust_endianness更改位置的字节序(这很好,因为错误的字节序u32是垃圾,但仍然是有效的u32)。

该代码有效,但关键问题是:这样安全吗?特别是,在某个时刻,data并且bytes两者都存在,它们是同一数据的一个可变且一个不变的切片。听起来很不好,对吧?

另一方面,我可以这样做:

let bytes = &data[..];
Run Code Online (Sandbox Code Playgroud)

这样,我也有这两个方面。所不同的只是 …

unsafe rust

9
推荐指数
1
解决办法
165
查看次数