GCC Rust Weekly Status Report 35

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

Milestone Progress

It’s 2022, and it is back to business for GCC Rust. We are now focusing on macros and config expansions, the last prominent missing feature preventing us from attempting to compile libcore. Macro expansion in Rust is very powerful combined with config expansions, Rust can generate complex code and, like a C/C++ preprocessor branch code based on conditional statements. The milestone is not thoroughly planned yet as we already have some code in place, and I am assessing what we need to do and what we can leverage. For example, the name resolution pass could be split into name resolution and name resolution late like the Rust compiler to resolve macros.

We also hope to be part of GSoC 2022 this year, so I will be spending some time considering different example projects this year and updating our wiki’s in due course.

Goal Testcase

After finishing up the previous milestone to add initial support for the match expression, I tested our goal test case (https://github.com/Rust-GCC/gccrs/issues/682), this has been very useful, and we will be continuing to test this continuously. The prominent missing features to compile the program are slices that include range-based for loops. Overall if we isolate the code outside of the usage of slices, we can compile this when we pull in the libcore impl block for u32 so that we have access to the methods wrapping_add and rotate_right. To track the effort going on here, I have been adding issues/pr’s to the task list of that GitHub issue so we can see over time all the effort it took to get this working. Many of the bugs found have already been fixed, but most importantly, this time spent testing informs how the compiler progresses and finds any bias or missed features early.

Monthly Community Call

We usually have this on the first Friday of the month but since it was the new year I decided to push it back to allow people to get back into a routine. See details below for details:

Completed Activities

  • HIR Visitor refactor and cleanup PR846
  • Bug Fix duplicate symbol generation PR847
  • Add support bitwise operator overloading PR848
  • Fix ICE on generic enum which contained dataless variants PR859
  • Add overflow checking on integer and floating point literals PR860
  • Support Wildcard patterns in match expressions PR866
  • Bug Fix using wildcard bindings in let statements PR868

Contributors this Week

Overall Task Status

CategoryLast WeekThis WeekDelta
TODO8899+11
In Progress1619+3
Completed257262+5
GitHub Issues

Test Cases

CategoryLast WeekThis WeekDelta
Passing54115521+110
Failed
XFAIL2121
XPASS
make check-rust

Bugs

CategoryLast WeekThis WeekDelta
TODO2433+9
In Progress46+2
Completed9094+4
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 202129th Nov 2021
Macros and cfg expansion0%0%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

  • Finish planning work for CFG and Macro expansion
  • Plan some GSoC 2022 projects
  • Complete bug fixes for Method Resolution
  • Begin work on Slices

Detailed changelog

Add overflow checking on Literal’s

This checks that the literal value is within the bounds of their respective types. I have omitted code fixing the other issue in the bug report that overflow/max_val integers should be saturated to infinity when cast to REAL_TYPE’s this seems like something we really should have documentation to reference in the code as to why this is the correct Rust behaviour.

fn test() -> i32 {
    return 10000000000000000000000000000000000000000000;
}
<source>:2:12: error: integer overflows the respective type 'i32'
    2 |     return 10000000000000000000000000000000000000000000;
      |            ^

Support wildcard bindings within let statements

In modern languages its common to sometimes need to be able to ignore bindings, its most commonly used in lambda’s or tuple destructuring, which we do not support yet. This patch now allows us not to ICE when we use wildcard bindings in general.

fn test(a: i32, _: i32) {
    let _ = 42 + a;
}

Support wildcard within Match Expression

The wildcard pattern ‘_’ acts akin to the default case within a switch statement in other languages. GCC CASE_LABEL_EXPR’s contain operand 0 and 1, operand 0 is used for the low value of a case label and operand 1 for a high value. So with this CASE_LABEL_EXPR is is possible to support a range of values from low->high if set apropriately, but for the wildcard case this is effectively a default case which means we set both operand 0 and 1 to NULL_TREE.

fn inspect(f: Foo) {
    match f {
        Foo::A => unsafe {
            let a = "Foo::A\n\0";
            let b = a as *const str;
            let c = b as *const i8;

            printf(c);
        },
        Foo::D { x, y } => unsafe {
            let a = "Foo::D %i %i\n\0";
            let b = a as *const str;
            let c = b as *const i8;

            printf(c, x, y);
        },
        _ => unsafe {
            let a = "wildcard\n\0";
            let b = a as *const str;
            let c = b as *const i8;

            printf(c);
        },
    }
}

Bitwise operator overloading

We missed the mappings for the following lang items which are used for all bitwise arithmetic.

  • bitand: libcore/ops/bit.rs
  • bitor: libcore/ops/bit.rs
  • bitxor: libcore/ops/bit.rs
  • shl: libcore/ops/bit.rs
  • shr: libcore/ops/bit.rs
  • bitand_assign: libcore/ops/bit.rs
  • bitor_assign: libcore/ops/bit.rs
  • bitxor_assign: libcore/ops/bit.rs
  • shl_assign: libcore/ops/bit.rs
  • shr_assign: libcore/ops/bit.rs

Now that these mappings are added we can compile code such as:

extern "C" {
    fn printf(s: *const i8, ...);
}

#[lang = "bitand_assign"]
pub trait BitAndAssign<Rhs = Self> {
    fn bitand_assign(&mut self, rhs: Rhs);
}

impl BitAndAssign for i32 {
    fn bitand_assign(&mut self, other: i32) {
        *self &= other;

        unsafe {
            let a = "%i\n\0";
            let b = a as *const str;
            let c = b as *const i8;

            printf(c, *self);
        }
    }
}

fn main() -> i32 {
    let mut a = 1;
    a &= 1;

    0
}

Leave a Reply

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