GCC Rust Weekly Status Report 39

Thanks again to Open Source Security, inc and Embecosm for their ongoing support for this project.

Milestone Progress

Macros are still under development; the code still needs more work before it can be merged. So this week, I will focus on compiling simple macros like an add macro that we enforce two expressions as the first part of the implementation that we can merge. This will serve as a jumping point to get into more complex macro rules.

This work on macros has indirectly improved how we can work with attributes, so to take advantage of this, we merged code to support the rust inline attribute.

Other than working on macros, I merged a lot of code cleanup in our code generation pass; this means we have one canonical path in how we compile functions now, which helps us handle attributes and ABI options without any duplication.

Completed Activities

  • Refactor TypeKind ToString from header to implementation PR911
  • Bug Fix multiple generic substitution on path expressions PR912
  • Support the inline attribute PR916 PR922
  • Reuse C/C++ front-end mark_addressable code PR917
  • Cleanup code generation to remove duplication PR918
  • Support deref_mut lang item during method resolution PR920

Overall Task Status

CategoryLast WeekThis WeekDelta
TODO106105-1
In Progress1111
Completed279284+5
GitHub Issues

Test Cases

CategoryLast WeekThis WeekDelta
Passing56865746+60
Failed
XFAIL2121
XPASS
make check-rust

Bugs

CategoryLast WeekThis WeekDelta
TODO3838
In Progress11
Completed105107+2
GitHub Bugs

Milestones Progress

MilestoneLast WeekThis WeekDeltaStart DateCompletion DateTarget
Data Structures 1 – Core100%100%30th Nov 202027th Jan 202129th Jan 2021
Control Flow 1 – Core100%100%28th Jan 202110th Feb 202126th Feb 2021
Data Structures 2 – Generics100%100%11th Feb 202114th May 202128th May 2021
Data Structures 3 – Traits100%100%20th May 202117th Sept 202127th Aug 2021
Control Flow 2 – Pattern Matching100%100%20th Sept 20219th Dec 202129th Nov 2021
Macros and cfg expansion45%50%+5%1st Dec 202128th Mar 2022
Imports and Visibility0%0%29th Mar 202227th May 2022
Const Generics0%0%30th May 202225th Jul 2022
Intrinsics0%0%6th Sept 202130th Sept 2022
GitHub Milestones

Risks

RiskImpact (1-3)Likelihood (0-10)Risk (I * L)Mitigation
Rust Language Changes3721Keep up to date with the Rust language on a regular basis
Going over target dates3515Maintain status reports and issue tracking to stakeholders

Planned Activities

  • Merge macro xfail testcases
  • Continue work macros
  • Add more good-first-pr issues with guides

Detailed changelog

inline attributes

In Rust the inline attribute takes three forms:

  • #[inline]
  • #[inline(always)]
  • #[inline(never)]

Inline without any option is analogous to C style inline keyword giving a hint to the compiler that this function is a good candidate for inlining. Inline always can be acheived with GCC’s inline always attribute: https://gcc.gnu.org/onlinedocs/gcc/Inline.html. Finally never we can mark functions as DECL_UNINLINEABLE. The one difference is that inline optimizations require optimizations to be enabled. So when compiling at -O0 no inlining will occur, any level greater than this, the inline pass will be enforced.

We have always added some simple error handling for bad inline options such as:

#[inline(A)]
fn test() {}
test.rs:2:3: error: unknown inline option
    2 | #[inline(A)]
      |   ^
#[inline(A,B)]
fn test() {}
test.rs:5:3: error: invalid number of arguments
    5 | #[inline(A, B)]
      |   ^

deref_mut lang item

Work on method resolution has continued steadily and we now support the deref_mut lang item so that for methods that require a &mut self reference we try to lookup any relevant deref_mut lang item to get the indirection required from the receiver.

extern "C" {
    fn printf(s: *const i8, ...);
}
                                           
#[lang = "deref"]
pub trait Deref {
    type Target;

    fn deref(&self) -> &Self::Target;
}

#[lang = "deref_mut"]
pub trait DerefMut: Deref {
    fn deref_mut(&mut self) -> &mut Self::Target;
}

impl<T> Deref for &T {
    type Target = T;

    fn deref(&self) -> &T {
        *self
    }
}

impl<T> Deref for &mut T {
    type Target = T;
    fn deref(&self) -> &T {
        *self
    }
}

pub struct Bar(i32);      
impl Bar {
    pub fn foobar(&mut self) -> i32 {
        self.0  
    }
}

pub struct Foo<T>(T);
impl<T> Deref for Foo<T> {
    type Target = T;

    fn deref(&self) -> &Self::Target {
        &self.0
    }
}

impl<T> DerefMut for Foo<T> {
    fn deref_mut(&mut self) -> &mut Self::Target {
        unsafe {
            let a = "mut_deref\n\0";
            let b = a as *const str;
            let c = b as *const i8;

            printf(c);
        }

        &mut self.0
    }
}

pub fn main() -> i32 {
    let bar = Bar(123);
    let mut foo: Foo<Bar> = Foo(bar);
    let foobar = foo.foobar();

    foobar - 123
}

See https://godbolt.org/z/xcM9ohcjK

Leave a Reply

Your email address will not be published. Required fields are marked *