Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Minimal codegen support: numbers and function paramters #2

Open
wants to merge 26 commits into
base: main
Choose a base branch
from

Conversation

Wybxc
Copy link
Contributor

@Wybxc Wybxc commented Sep 12, 2024

This is a minimal yet complete C code generation implementation, capable of compiling functions with number-typed parameters and as expressions.

The structure is organized as follows:

  • crates/rustc_codegen_c: Implementation of the codegen backend.
  • crates/rustc_codegen_c_ast: C syntax structure for generating C source code.
  • bootstrap: Build system for executing rustc with this codegen backend enabled.
  • example: Example files demonstrating the capabilities of the codegen backend.
  • tests: Test cases for validating functionality.

@tgross35
Copy link
Contributor

tgross35 commented Sep 17, 2024

Thanks for getting this started! Is it possible to put bootstrap and CI into its own PR so that can be merged first, before the codegen part?

(it will take me a little while to review this all, still don't have my usual github access)

@Wybxc
Copy link
Contributor Author

Wybxc commented Sep 19, 2024

Understood, I'm working on #3

@Wybxc Wybxc mentioned this pull request Sep 20, 2024
@tgross35
Copy link
Contributor

This can be rebased now that #3 merged. If it is possible to split this further for smaller review units then that would be great (e.g. AST crate first and codegen separately), but if not than this shouldn't be too bad with bootstrap out of the picture.

@tgross35
Copy link
Contributor

Could you put the license files into a separate PR that we can merge right away? Guess we are currently unlicensed.

Otherwise I'll try to look at this tomorrow-ish.

Copy link
Contributor

@tgross35 tgross35 left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Added some initial comments, but I still have a lot more to go through.

Could you please add documentation comments? Most everything that isn't a trait implementation or a trivial function could benefit (it's a bit tough to figure out how things fit together without them).

README.md Outdated Show resolved Hide resolved
.rustfmt.toml Outdated Show resolved Hide resolved
bootstrap/src/test.rs Outdated Show resolved Hide resolved
@@ -106,6 +112,19 @@ impl TestCase {
log::debug!("running {:?}", command);
command.status().unwrap();
}

pub fn build_lib(&self, manifest: &Manifest) {
std::fs::create_dir_all(self.output.parent().unwrap()).unwrap();
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

let output_dir = self.output.parent().unwrap() since it is used twice. But why do you need to navigate to the parent directory for this?

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@Wybxc could you clarify why this needs to change to the parent directory of output? That doesn't seem to make sense.

example/example.rs Outdated Show resolved Hide resolved
@@ -0,0 +1,130 @@
#![feature(no_core, lang_items, rustc_attrs, intrinsics, decl_macro)]
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This file has a lot of extra comments that should be removed before merge. Also should get a //! comment saying what its purpose is, even though it's semi-obvious.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

tests/auxiliary/ would probably be a better place for this file, since it's not really an example. And this would mirror rust-lang/rust#130693.

crates/rustc_codegen_c_ast/src/arena.rs Outdated Show resolved Hide resolved
crates/rustc_codegen_c_ast/src/expr.rs Outdated Show resolved Hide resolved
crates/rustc_codegen_c_ast/src/lib.rs Show resolved Hide resolved
Comment on lines +19 to +27
#[derive(Clone, Copy)]
pub struct ModuleCtxt<'mx>(pub &'mx ModuleArena<'mx>);
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Nit: ctx is usually the abbreviation we use in the compiler (rather than ctxt)

Comment on lines +6 to +15
pub type CDecl<'mx> = &'mx CDeclKind<'mx>;

#[derive(Debug, Clone)]
pub enum CDeclKind<'mx> {
// Typedef { name: String, ty: CType },
// Record { name: String, fields: Vec<CDecl> },
// Field { name: String, ty: CType },
// Enum { name: String, values: Vec<CEnumConstant> },
Var { name: CValue, ty: CTy<'mx>, init: Option<CExpr<'mx>> },
}
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Any sort of type like this that has a C representation should get a small example of produced code in the doc comment (i.e. for each enum variant here).

}
}

impl Printer {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think this logic should be reversed. That is, currently the whole thing looks like:

impl Printer {
    fn print_decl(&mut self, ...) { /* ... */ }
    fn print_other_thing(&mut self, ...) { /* ... */ }
    // ...
}

But this should be moved to a trait:

// Renamed from `Printer`
struct PrintCtx { pp: /* ... */ }

trait Print {
    fn print(&self, ptx: &mut PrintCtx);
}

And then that gets implemented for CDecl and all the other types.

@@ -0,0 +1,131 @@
//! Pretty printing

// TODO: pretty printing test
Copy link
Contributor

@tgross35 tgross35 Sep 30, 2024

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

In the interest of time it is okay to not do the most fine-grained testing, but something is needed here. I would suggest you just add some simple output tests; in each module you can have a couple small tests that just construct an AST and print it to a string, then compare against a saved file. If RUSTC_BLESS is set, overwrite the file.

@tgross35
Copy link
Contributor

rustc_codegen_c_ast is pretty self-contained, it would be good to move that to its own PR as well.

@@ -0,0 +1,18 @@
// CHECK: filename

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

In addition to the filecheck tests, you should add a couple of blessed tests. Add tests/codegen-output/, teach bootstrap to codegen all the .rs files and assert their output matches a .c of the same name in the same directory. And then add a --bless argument to bootstrap that will update the .c file.

Don't use that for complex tests where the MIR output is likely to change. But this would be good for simple tests like this one, and also is nice to show what the expected output is.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Also - these tests should get a comment about what they are intended to test. I'm not sure what this one is supposed to do.

tests/codegen/ret_value.rs Outdated Show resolved Hide resolved
@@ -0,0 +1,18 @@
// CHECK: filename

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Also - these tests should get a comment about what they are intended to test. I'm not sure what this one is supposed to do.

tests/codegen/params_count.rs Outdated Show resolved Hide resolved
@@ -1,5 +0,0 @@
use rustc_middle::ty::TyCtxt;
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This file gets emptied, any reason to keep it?

@@ -0,0 +1,5 @@
/** cast from unsigned to signed
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Could you add a file-level doc comment explaining what helper.h is?

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

2 participants