GCC Front-End For Rust

Alternative Rust Compiler for GCC

View the Project on GitHub

July 2023 Monthly report

Overview

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

Milestone Progress

A lot of progress was done in almost all areas of the compiler this month, with improvements being done on all stages of our pipeline: our GSoC student Raiki Tamura made some significant changes to the lexer and added multiple routines around unicode handling. Furthermore, they are bringing a Unicode Normalization generator to the compiler, allowing us to easily keep up to date with the latest Unicode standard. Mahad Muhammad, on the other hand, keeps dwelving into the guts of the compiler, looking for error codes to add and raising issues as they go. Both of these works are extremely useful as we get closer and closer to attempting to run the rustc testsuite. Both students had their mid-term evaluation this month, and passed it with flying colors. Congratulations both! And thank you for your continued work.

We are also getting a lot of contributions from Owen Avery, who has done an amazing job cleaning up some of the older, unecessary abstractions still present in the compiler. Marc Poulhiès merged his new HIR dump visitor, which is proving to be very helpful for debugging this stage of the compilation pipeline, which Philip is working on to get the last few bits of iterators working. Keeping on the HIR side of things, Jakub Dupak has started their work on facts generation for the polonius-engine library, which will help in bringing borrow-checking to the compiler. This work is extremely experimental, but they are making good progress and we are excited to see where it goes! On the other hand of the compiler, Arthur and Pierre-Emmanuel are working on the new name resolution algorithm, which is proving to be time-consuming but extremely rewarding. The new resolver code is simple and should be easy to maintain. We have completed the work necessary for macro name resolution, an important part of the “early” name resolution in Rust, and are now working to complete procedural macro resolution. At the same time, Philip and Arthur will start work on “late” name resolution, plugging together our new resolver and the existing typechecker where necessary. Once these last few steps will be completed, we should be in a very good position to succesfully compile Rust’s 1.49 core library.

In total, the work this month totaled 88 pull-requests merged. This is an extremely impressive number, and one of the highest we have had since the beginning of the project. The team is extremely thankful to all the contributors, and to all of the amazing people we get to interact with.

In other news, the GCC project has published a Code of Conduct, which the gccrs project adopted. If you remember, we were previously using the Rust Project’s Code of Conduct, which suited us nicely. During the last community meeting, we reviewed the new Code of Conduct and decided to switch to it, as it contains similar community requirements. We are also getting ready for conference season, during which we plan on giving two talks: one at the GNU Cauldron in Cambridge at the end of September, and one in Brussels for EuroRust in October. We hope to meet a lot of people once again!

Community call

We will have our next monthly community call on the 14th of August 2023. You can subscribe to our calendar to see when the next one will be held. The call is open to everyone, even if you would just like to sit-in and listen. You can also subscribe to our mailing-list or join our Zulip chat to be notified of upcoming events.

Completed Activities

Contributors this month

Overall Task Status

Category Last Month This Month Delta
TODO 237 252 +15
In Progress 46 52 +6
Completed 696 721 +25

Test Cases

TestCases Last Month This Month Delta
Passing 7974 8094 +120
Failed - - -
XFAIL 53 69 +16
XPASS - - -

Bugs

Category Last Month This Month Delta
TODO 73 90 +17
In Progress 22 27 +5
Completed 346 354 +8

Milestones Progress

Note that the intrinsics milestone percentage on github is not representative: It shows a 73% completion rate, but does not take into account the tracking issues with dozens of unresolved items. Thus the percentage is computed using the sum of issues and tracked items done divided by the sums of issues and tracked items overall. Similarly, the Update GCC’s master branch milestone contains a tracking issue containing over 200 tasks. The percentage shown here takes this into account.

Milestone Last Month This Month Delta Start Date Completion Date Target
Data Structures 1 - Core 100% 100% - 30th Nov 2020 27th Jan 2021 29th Jan 2021
Control Flow 1 - Core 100% 100% - 28th Jan 2021 10th Feb 2021 26th Feb 2021
Data Structures 2 - Generics 100% 100% - 11th Feb 2021 14th May 2021 28th May 2021
Data Structures 3 - Traits 100% 100% - 20th May 2021 17th Sep 2021 27th Aug 2021
Control Flow 2 - Pattern Matching 100% 100% - 20th Sep 2021 9th Dec 2021 29th Nov 2021
Macros and cfg expansion 100% 100% - 1st Dec 2021 31st Mar 2022 28th Mar 2022
Imports and Visibility 100% 100% - 29th Mar 2022 13th Jul 2022 27th May 2022
Const Generics 100% 100% - 30th May 2022 10th Oct 2022 17th Oct 2022
Initial upstream patches 100% 100% - 10th Oct 2022 13th Nov 2022 13th Nov 2022
Upstream initial patchset 100% 100% - 13th Nov 2022 13th Dec 2022 19th Dec 2022
Update GCC’s master branch 100% 100% - 1st Jan 2023 21st Feb 2023 3rd Mar 2023
Final set of upstream patches 100% 100% - 16th Nov 2022 1st May 2023 30th Apr 2023
Borrow Checking 1 0% 0% - TBD - 15th Aug 2023
AST Pipeline for libcore 1.49 70% 75% +5% 13th Apr 2023 - 1st Jul 2023
HIR Pipeline for libcore 1.49 67% 67% - 13th Apr 2023 - TBD
Procedural Macros 1 70% 70% - 13th Apr 2023 - 6th Aug 2023
GCC 13.2 Release 42% 100% +58% 13th Apr 2023 22nd Jul 2023 15th Jul 2023
GCC 14 Stage 3 0% 0% - TBD - 1st Nov 2023
core 1.49 functionality [AST] 0% 0% - 1st Jul 2023 - 1st Nov 2023
Rustc Testsuite Prerequisistes 0% 0% - TBD - 1st Sep 2023
Intrinsics and builtins 18% 18% - 6th Sep 2022 - TBD
Const Generics 2 0% 0% - TBD - TBD
Rust-for-Linux compilation 0% 0% - TBD - TBD

Testing project

Testsuite Compiler Last month This month Success delta
rustc testsuite gccrs -fsyntax-only - 92.6% -
gccrs testsuite rustc stable - 59.2% -
rustc testsuite passing tests gccrs - 14.0% -
rustc testsuite (nostd) gccrs - 27.5% -
rustc testsuite (nocore) gccrs - 3.8% -
blake3 gccrs - 25.0% -
libcore gccrs - 0% -

Planned Activities

Detailed changelog

HIR Dump

We now have a great starting point to a working HIR dump. It does not conform directly to Rustc but we don’t need it to. We have desperatly needed this for quite some time to help newer developers debug in the backend code generation as well as the typesystem and HIR lints. The HIR contains a bunch of mapping information and these ID’s are crucial to help with debugging issues.

Crate [                                                                                                                                                                      
        inner_attrs: empty                                                            
        mapping: [C: 0 Nid: 72 Hid: 59]                                                                                                                                      
        items {                                                                                                                                                              
                Trait [                                                                                                                                                      
                        mapping: [C: 0 Nid: 6 Hid: 21 Lid: 2]                                                                                                                
                        outer_attributes {                                                                                                                                   
                                lang = sized                                                                                                                                 
                        } // outer_attributes                                                                                                                                
                        visibility: pub                                                                                                                                      
                        unsafety: 0                                                   
                        name: Sized                                                                                                                                          
                        generic_params {                                                                                                                                     
                                TypeParam [                                                                                                                                  
                                        outer_attr:                                                                                                                          
                                        type_representation: Self                                                                                                            
                                        type_param_bounds: empty                                                                                                             
                                        type: none                                                                                                                           
                                ] // TypeParam                                                                                                                               
                        } // generic_params 
                        type_param_bounds: empty
                        where clause: none
                        trait_items: empty
                ] // Trait
                TupleStruct [
                        mapping: [C: 0 Nid: 20 Hid: 29 Lid: 8]
                        outer_attributes: empty
                        visibility: private 
                        struct_name: GenericStruct
                        generic_params {
                                TypeParam [ 
                                        outer_attr: 
                                        type_representation: T
                                        type_param_bounds: empty
                                        type: none
                                ] // TypeParam
                        } // generic_params 
                        where_clause: none
                        fields {

We will be making changes to this going forward but having a starting point gives us the chance to move forward.

More error codes

This month saw us adding these error codes to our diagnostics:

  1. E0572
  2. E0571
  3. E0268
  4. E0045
  5. E0323
  6. E0423
  7. E0133
  8. E0658
  9. E0093
  10. E0124
  11. E0070
  12. E0063
  13. E0045
  14. E0053
  15. E0046
  16. E0061
  17. E0229
  18. E0034

With the continued push forward with more error codes each week it shows GCC Rust is able to catch errors at the right points to emit these error codes. Lots have already been added this is just the list for this month.

Fix ICE with return expression outside of context

This was a nice bug to fix because you can’t return outside of a function context.

const FOO: u32 = return 0; 

This was an access to an empty stack which would not have been allowed if we wrote this in Rust. We now emit

test.rs:1:18: error: return statement outside of function body
    1 | const FOO: u32 = return 0;
      |                  ^~~~~~

Fix ICE when using full path to enum variant as part of a TypePath

It is not allowed to use the variant of an enum as a Type, rust enforces that you must use the Enum itself as a type. For example

enum Dragon {
    Born,
}

fn oblivion() -> Dragon::Born {
    Dragon::Born
}

We now emit:

test.rs:5:26: error: expected type, found variant of Dragon
    5 | fn oblivion() -> Dragon::Born {
      |                          ^~~~

Sized marker trait

In Rust all generic type parameters implement the Sized marker trait by default. This means for an example such as:

fn foo<T>(a:T) -> X { ... }

Will always get turned into:

#[lang = "sized"]
pub trait Sized {}

fn foo<T: Sized>(a:T) -> X { ... }

Types such as Slices, Dyn traits do not implement sized so we need to use the special syntax of ?Sized to remove the Sized trait obligation

#[lang = "sized"]
pub trait Sized {}

pub trait Trait {
    fn foo(&self) -> Self
    where
        Self: Sized;
}

pub fn static_foo<T: Trait + ?Sized>(_b: &T) {}

pub fn dynamic_bar(a: &dyn Trait) {
    static_foo(a)
}

Note in the example, Trait’s define an implicit Self type parameter which does not implemented Sized by default. This is because it would cause a recursive trait obligation for Sized to be defined on the Self for the Sized trait itself.

This is a key milestone for gccrs as it lays the groundwork to support the other major marker-trait of Drop. As the Sized trait is so intrinsic to Rust this has enforced us to update most of the testsuite to include this marker-trait.

Track Fn trait fnonceoutput

In order to setup the Output associated type we can rely on using generic argument bindings. So for example when we have the FnOnce trait:

#[lang = "fn_once"]
pub trait FnOnce<Args> {
    #[lang = "fn_once_output"]
    type Output;

    extern "rust-call" fn call_once(self, args: Args) -> Self::Output;
}

Then we might have a function such as:

pub fn map<R, F: FnOnce(T) -> R>(self, f: F) -> Option<R> { ... }

For this trait bound predicate of FnOnce(T) -> R we use syntactic sugar to setup generics for the bound as if it was just another generic trait such as:

FnOnce<(T), Output=R>

Note the argument T is wrapped up implicitly inside a Tuple this keeps the type system consistent so you don’t need to have specific traits for numbers of arguments. Resuing argument binding means we can reuse our generic argument handling to get this support for free which is then consistent across the compiler.