-
Notifications
You must be signed in to change notification settings - Fork 216
Add mse63 Final Project #533
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
Conversation
sampsyo
left a comment
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Thanks for the writeup. It sounds like you eventually took my advice from #513 and did not attempt any of the "decompiler" aspects—focusing instead on the straightforward "C backend" aspects. Which makes sense! Even a simple CFG recovery strategy would be complicated to do.
Would you be interested in contributing your bril2c compiler to the Bril monorepo? I can imagine it being useful to other folks down the line!
content/blog/2025-05-bril2c.md
Outdated
| name = "Mahmoud Elsharawy Sampson" | ||
| +++ | ||
|
|
||
| # Bril2C |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
No need to repeat the post title; it's already rendered by default.
content/blog/2025-05-bril2c.md
Outdated
| +++ | ||
|
|
||
| # Bril2C | ||
| This project is intended to translate code from Bril (Big Red Intermediate Language) to C. Bril is an educational intermediate language used in the CS6120 course at Cornell University. As an intermediate language, it is low-level, which would make it difficult to translate to a high-level language. However, C, with features such as manual memory management and goto statements, makes it a natural choice. In my initial proposal, I thought creating a complete and correct translation from Bril to C would be trivial, but indeed quite a bit of hacking was needed, due to limitations of C not placed on Bril. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
It might be helpful to add a hyperlink when you introduce Bril.
content/blog/2025-05-bril2c.md
Outdated
| ## Implementation | ||
| Bril2C is written in Rust, using the "bril-rs" package. Most of the actual translation work happens in a single trait, `Crep`, which contains a single function `crep(self) -> String`. Each piece of Bril implements this function with how it translates itself to C, calling `crep` on smaller pieces, effectively inducting on the structure of the program. For example, `crep` for a program will, along with other things, call `crep` for each function in that program, which will call `crep` for each instruction, which will call `crep` for each operation and variable. In this way, adding additional features of Bril into C becomes as easy as implementing a single function for a specific type. | ||
|
|
||
| As it turns out, quite some fiddling is required to get even a majority of Bril code working. Almost all of the benchmarks have `main` function which takes in arguments, something not possible in `C`. We get around this by creating our own `main` function in C, which parses arguments from the command line, and passes them into a copy that's supposed to represent the Bril's main function, called `main_f`. Taking an example, `sum-bits.bril`, with a main function that takes in a single integer argument, this is represented as: |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
No need for backticks around C, the name of the programming language.
| int64_t: printf("%" PRId64 " ", x), | ||
| uint8_t: printf("%s ", (x) ? "true" : "false"), | ||
| double: printf("%.17f ", x)) | ||
| ``` |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Interesting approach to supporting print! FWIW, for both the issue of main arguments and for print, there is a way that you could consider simplifying code generation by reusing an existing "runtime library" for one of the other Bril-to-native compilers, like this:
https://github.com/sampsyo/bril/blob/main/brilift/rt.c
That's a library of little C functions that do things like parse each command-line argument or print something of a particular type. You can use the Bril type information to select the appropriate _bril_print_* function.
content/blog/2025-05-bril2c.md
Outdated
| return diff_; | ||
| } | ||
| ``` | ||
| At this point, you may have noticed the additional characters in each variable name and suffix name. These are inserted to prevent bril registers from being confused with C keywords, which is surprisingly popular in Bril code, especially for words like `if` and `continue`. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
bril -> Bril
content/blog/2025-05-bril2c.md
Outdated
| uint8_t: printf("%s ", (x) ? "true" : "false"), | ||
| double: printf("%.17f ", x)) | ||
| ``` | ||
| For ease of programming, each function declares all of the variables used in it at the beginning of the function After that, it's a "simple" translation from Bril instructions to C statements. Therefore, the following function in Bril: |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
| For ease of programming, each function declares all of the variables used in it at the beginning of the function After that, it's a "simple" translation from Bril instructions to C statements. Therefore, the following function in Bril: | |
| For ease of programming, each function declares all of the variables used in it at the beginning of the function. After that, it's a "simple" translation from Bril instructions to C statements. Therefore, the following function in Bril: |
content/blog/2025-05-bril2c.md
Outdated
| ``` | ||
|
|
||
| ## Evaluation | ||
| Creating a program to translate a single Bril program into C is easy. Creating a program to translate _every_ bril program into C is much more difficult. I tested my code with a simple script, `test.sh` which would run every `.bril` file in `benchmarks`, and compare its output with the translated, compiled, and run code from `Bril2C`. Many times, I thought I had completed my project, only to discover a Bril program that broke my seemingly correct implementation, such as by naming a register the same name as a function, or by using the same register with two different types in two different functions. I did manage to resist the temptation of simply declaring that I would only consider a subset of Bril programs with "nice" formatting, however, and powered on, handling edge case after edge case. After enough bug-fixing, however, I was able to successfully produce a correct program for every single Bril program in the benchmark (as shown in `test_results.txt`). |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Cool! Can you add a link to that results file, test_results.txt?
content/blog/2025-05-bril2c.md
Outdated
| Mahmoud is an MEng student enrolled in CS6120 as of Spring 2025. | ||
| """ | ||
| [[extra.authors]] | ||
| name = "Mahmoud Elsharawy Sampson" |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Do you have a secret last name?
|
I just pushed a new commit to fix the issues. |
|
Looks great; thanks! Why don't we start with a top-level |
Closes #513