rust-gcc / gccrs Goto Github PK
View Code? Open in Web Editor NEWGCC Front-End for Rust
Home Page: https://rust-gcc.github.io/
License: GNU General Public License v2.0
GCC Front-End for Rust
Home Page: https://rust-gcc.github.io/
License: GNU General Public License v2.0
We are missing the GPL info at the top of some files.
We should respect the mut keyword on declarations such as:
let mut x;
x = 1;
x = 2;
We should add support to compile raw str strings to GIMPLE.
let x = "mystring"
This ticket is to track the implementation of arrays there is an already open PR #51
The resolution rules are not well documented in Rust doc, the rustc relies on librustc_resolve.
I'm going to list all the rules here (or wiki) for the reference.
I'm here to list the features described in RFCs but haven't implemented them in rustc
. We'll follow rustc
at present, and let them be enhancements in the future.
I had zulip permissions wrongly setup, please feel free to join. https://gcc-rust.zulipchat.com/
We need to add in float data type to be supported
This relates to something I had thought about doing, but not in enough detail to open an enhancement issue. gcc supports something called "rich locations" in which three actual locations are encoded - a "start" location, a "caret" location, and an "end" location - basically like a location range with a specified value highlighted.
I couldn't find the page that I thought I originally read this in, but here's a quote from here:
As of GCC 6, ordinary locations changed from supporting just a point in the user’s source code to supporting three points: the caret location, plus a start and a finish:
a = foo && bar;
~~~~^~~~~~
| | |
| | finish
| caret
start
Instead of accessing start_location
and end_location
separately, these could be integrated into a single location value. There's also the technicality that the current definition of get_closing_locus()
technically gets the beginning location of the last statement rather than the end location of the block (i.e. the right curly bracket), assuming that this would be the preferred behaviour.
The lexer would have to be modified to reflect this rich location system, and the parser and AST probably would have to be too (i.e. make a new location from the "start" location from one token and the "end" location of a different one). Also, the backend-independent Location
abstraction would have to be modified to support this.
Originally posted by @SimplyTheOther in #90 (comment)
I'm going to try a bigger contribution, however, I realized that we don't have a unified indentation standard. It's better to have an auto-indentation configuration. Here I have a clang-format
, anyone can use their preferred auto-indentation tool without bothering to do it manually. The modern IDE/editor can recognize it and auto-indent.
---
Language: Cpp
# BasedOnStyle: LLVM
AccessModifierOffset: -2
AlignAfterOpenBracket: Align
AlignConsecutiveAssignments: false
AlignConsecutiveDeclarations: false
AlignEscapedNewlinesLeft: true
AlignOperands: true
AlignTrailingComments: true
AllowAllParametersOfDeclarationOnNextLine: true
AllowShortBlocksOnASingleLine: false
AllowShortCaseLabelsOnASingleLine: false
AllowShortFunctionsOnASingleLine: Empty
AllowShortIfStatementsOnASingleLine: false
AllowShortLoopsOnASingleLine: false
AlwaysBreakAfterDefinitionReturnType: None
AlwaysBreakAfterReturnType: None
AlwaysBreakBeforeMultilineStrings: false
AlwaysBreakTemplateDeclarations: false
BinPackArguments: true
BinPackParameters: true
BraceWrapping:
AfterClass: false
AfterControlStatement: false
AfterEnum: false
AfterFunction: false
AfterNamespace: false
AfterObjCDeclaration: false
AfterStruct: false
AfterUnion: false
BeforeCatch: false
BeforeElse: false
IndentBraces: false
BreakBeforeBinaryOperators: All
BreakBeforeBraces: Allman
BreakBeforeTernaryOperators: true
BreakConstructorInitializersBeforeComma: false
BreakAfterJavaFieldAnnotations: false
BreakStringLiterals: true
ColumnLimit: 120
CommentPragmas: '^ IWYU pragma:'
ConstructorInitializerAllOnOneLineOrOnePerLine: false
ConstructorInitializerIndentWidth: 2
ContinuationIndentWidth: 2
Cpp11BracedListStyle: true
DerivePointerAlignment: false
DisableFormat: false
ExperimentalAutoDetectBinPacking: false
ForEachMacros: [ foreach, Q_FOREACH, BOOST_FOREACH ]
IncludeCategories:
- Regex: '^"(llvm|llvm-c|clang|clang-c)/'
Priority: 2
- Regex: '^(<|"(gtest|isl|json)/)'
Priority: 3
- Regex: '.*'
Priority: 1
IncludeIsMainRegex: '$'
IndentCaseLabels: false
IndentWidth: 2
IndentWrappedFunctionNames: false
JavaScriptQuotes: Leave
JavaScriptWrapImports: true
KeepEmptyLinesAtTheStartOfBlocks: true
MacroBlockBegin: ''
MacroBlockEnd: ''
MaxEmptyLinesToKeep: 1
NamespaceIndentation: All
ObjCBlockIndentWidth: 2
ObjCSpaceAfterProperty: false
ObjCSpaceBeforeProtocolList: true
PenaltyBreakBeforeFirstCallParameter: 19
PenaltyBreakComment: 300
PenaltyBreakFirstLessLess: 120
PenaltyBreakString: 1000
PenaltyExcessCharacter: 1000000
PenaltyReturnTypeOnItsOwnLine: 60
PointerAlignment: Right
ReflowComments: true
SortIncludes: true
SpaceAfterCStyleCast: false
SpaceAfterTemplateKeyword: true
SpaceBeforeAssignmentOperators: true
SpaceBeforeParens: Always
SpaceInEmptyParentheses: false
SpacesBeforeTrailingComments: 1
SpacesInAngles: false
SpacesInContainerLiterals: true
SpacesInCStyleCastParentheses: false
SpacesInParentheses: false
SpacesInSquareBrackets: false
Standard: Cpp11
TabWidth: 2
Comments?
Dejagnu only outputs results to stdout and we need a post script to resolve this and fail the build on test failures.
We should be able to compile the enum data structure this may avoid the match control flow for now.
Mark W has done most of the leg work for this one over on: https://code.wildebeest.org/git/user/mjw/gccrs/commit/?h=enum-type
Shadowing of declarations need to be respected for core data structures such as:
let mut x;
x = 4;
let mut x;
x = true;
Rust uses a builtin akin to void in other languages this is a core data structure
We should be able to compile TupleStructs and Anon Tuples.
I'm working on an experimental branch to enhance -frust-dump-parse
which is a little inspired by gccgo's AST dump.
For example:
fn abc(x:u32, y:u32) -> u32 {
return x+y;
}
fn main() {
println!("Hello World!");
}
The dumped result looks like this:
Crate:
inner attributes: none
items:
u32 abc(x : u32, y : u32)
{
BlockExpr:
outer attributes: none
inner attributes: none
statements:
ExprStmtWithoutBlock: return ArithmeticOrLogicalExpr: x + y
final expression: none
}
void main()
{
BlockExpr:
outer attributes: none
inner attributes: none
statements:
ExprStmtWithoutBlock: println!("Hello World!")
final expression: none
}
The branch is nala/enhance/ast-dump
Comments are welcome.
I think it's better to separate type and name resolution, fortunately, if we do it now, it's just a little change. Here're the steps:
Resolution
class inherited from AST::ASTVisitor
, and move static bool ResolveNamesAndTypes
into it.TypeResolution
and NameResolution
class inherited from Resolution
class.This is better for maintenance and working parallelly.
And the name resolution will distinct names from different namespaces, like values, macros, so it's an important prerequisite for the rest of the work.
If it's OK, then I can raise PR for it.
What do you think? @philberty @SimplyTheOther
We should respect the basic lexical scoping of rust code. This will need extended later for lifetimes/generics etc.
test.rs:8:36: error: expecting ‘;’ but ‘]’ found
8 | let mut array: [i32; 3] = [0; 3];
| ^
test.rs:8:5: error: failed to parse statement or expression without block in block expression
8 | let mut array: [i32; 3] = [0; 3];
| ^
test.rs:8:36: error: unrecognised token ‘]’ for start of item
8 | let mut array: [i32; 3] = [0; 3];
| ^
test.rs:8:36: error: failed to parse item in crate
Link error on x86_64-pc-cygwin occurs.
Is configure option wrong?
Or gcc's bug?
$ cat hello.rs
fn main() {
println!("Hello, world!");
}
$ TMPDIR=/tmp /tmp/gcc-rust/usr/local/bin/gccrs.exe -v hello.rs
Using built-in specs.
COLLECT_GCC=/tmp/gcc-rust/usr/local/bin/gccrs
COLLECT_LTO_WRAPPER=/tmp/gcc-rust/usr/local/bin/../libexec/gcc/x86_64-pc-cygwin/10.0.0/lto-wrapper.exe
Target: x86_64-pc-cygwin
Configured with: ./configure --disable-bootstrap --enable-multilib --enable-languages=c,c++,rust
Thread model: single
Supported LTO compression algorithms: zlib zstd
gcc version 10.0.0 20191127 (experimental) (GCC)
COLLECT_GCC_OPTIONS='-v' '-shared-libgcc' '-mtune=generic' '-march=x86-64'
/tmp/gcc-rust/usr/local/bin/../libexec/gcc/x86_64-pc-cygwin/10.0.0/rust1.exe hello.rs -quiet -dumpbase hello.rs -mtune=generic -march=x86-64 -auxbase hello -version -L/tmp/gcc-rust/usr/local/bin/../lib/gcc/x86_64-pc-cygwin/10.0.0 -L/tmp/gcc-rust/usr/local/bin/../lib/gcc -L/tmp/gcc-rust/usr/local/bin/../lib/gcc/x86_64-pc-cygwin/10.0.0/../../../../lib -L/lib/../lib -L/usr/lib/../lib -L/tmp/gcc-rust/usr/local/bin/../lib/gcc/x86_64-pc-cygwin/10.0.0/../../.. -o /tmp/ccr9IdMy.s
GNU Rust (GCC) version 10.0.0 20191127 (experimental) (x86_64-pc-cygwin)
compiled by GNU C version 9.3.0, GMP version 6.2.0, MPFR version 4.0.2-p6, MPC version 1.1.0, isl version isl-0.22.1-GMP
GGC heuristics: --param ggc-min-expand=30 --param ggc-min-heapsize=4096
GNU Rust (GCC) version 10.0.0 20191127 (experimental) (x86_64-pc-cygwin)
compiled by GNU C version 9.3.0, GMP version 6.2.0, MPFR version 4.0.2-p6, MPC version 1.1.0, isl version isl-0.22.1-GMP
GGC heuristics: --param ggc-min-expand=30 --param ggc-min-heapsize=4096
Preparing to parse files.
about to parse expr (in expr without block method)
beginning null denotation identifier handling
current peek token when starting path pratt parse: '!'
current token (just about to return path to null denotation): '!'
finished null denotation identifier path parsing - next is branching
new delim token tree parsing begun
ast token created with str 'Hello, world!'
finished parsing new delim token tree - peeked token is now ';' while t is ')'
successfully parsed macro invocation (via partial)
finished parsing null denotation
null denotation is not null - going on to left denotation
initial rbp: '0', initial lbp: '0' (for ';')
successfully parsed expr in parse_expr - returning
successfully parsed expr (in expr without block method)
about to call the impl for clone expr without block
expr to expr without block conversion didn't error
expr to expr without block conversion was successful; returning
SUCCESSFULLY PARSED CRATE
ran register_plugins (with no body)
SUCCESSFULLY REGISTERED PLUGINS
started injection
finished injection
SUCCESSFULLY FINISHED INJECTION
started expansion
finished expansion
SUCCESSFULLY FINISHED EXPANSION
started name resolution
finished name resolution
SUCCESSFULLY FINISHED RESOLUTION
COLLECT_GCC_OPTIONS='-v' '-shared-libgcc' '-mtune=generic' '-march=x86-64'
as -o /tmp/ccpwggue.o /tmp/ccr9IdMy.s
COMPILER_PATH=/tmp/gcc-rust/usr/local/bin/../libexec/gcc/x86_64-pc-cygwin/10.0.0/:/tmp/gcc-rust/usr/local/bin/../libexec/gcc/
LIBRARY_PATH=/tmp/gcc-rust/usr/local/bin/../lib/gcc/x86_64-pc-cygwin/10.0.0/:/tmp/gcc-rust/usr/local/bin/../lib/gcc/:/tmp/gcc-rust/usr/local/bin/../lib/gcc/x86_64-pc-cygwin/10.0.0/../../../../lib/:/lib/../lib/:/usr/lib/../lib/:/tmp/gcc-rust/usr/local/bin/../lib/gcc/x86_64-pc-cygwin/10.0.0/../../../:/lib/:/usr/lib/
COLLECT_GCC_OPTIONS='-v' '-shared-libgcc' '-mtune=generic' '-march=x86-64'
/tmp/gcc-rust/usr/local/bin/../libexec/gcc/x86_64-pc-cygwin/10.0.0/collect2.exe -plugin /tmp/gcc-rust/usr/local/bin/../libexec/gcc/x86_64-pc-cygwin/10.0.0/cyglto_plugin-0.dll -plugin-opt=/tmp/gcc-rust/usr/local/bin/../libexec/gcc/x86_64-pc-cygwin/10.0.0/lto-wrapper.exe -plugin-opt=-fresolution=/tmp/ccHmliAY.res -plugin-opt=-pass-through=-lgcc_s -plugin-opt=-pass-through=-lgcc -plugin-opt=-pass-through=-lcygwin -plugin-opt=-pass-through=-ladvapi32 -plugin-opt=-pass-through=-lshell32 -plugin-opt=-pass-through=-luser32 -plugin-opt=-pass-through=-lkernel32 -plugin-opt=-pass-through=-lgcc_s -plugin-opt=-pass-through=-lgcc -m i386pep --wrap _Znwm --wrap _Znam --wrap _ZdlPv --wrap _ZdaPv --wrap _ZnwmRKSt9nothrow_t --wrap _ZnamRKSt9nothrow_t --wrap _ZdlPvRKSt9nothrow_t --wrap _ZdaPvRKSt9nothrow_t -Bdynamic --dll-search-prefix=cyg --tsaware /lib/../lib/crt0.o /tmp/gcc-rust/usr/local/bin/../lib/gcc/x86_64-pc-cygwin/10.0.0/crtbegin.o -L/tmp/gcc-rust/usr/local/bin/../lib/gcc/x86_64-pc-cygwin/10.0.0 -L/tmp/gcc-rust/usr/local/bin/../lib/gcc -L/tmp/gcc-rust/usr/local/bin/../lib/gcc/x86_64-pc-cygwin/10.0.0/../../../../lib -L/lib/../lib -L/usr/lib/../lib -L/tmp/gcc-rust/usr/local/bin/../lib/gcc/x86_64-pc-cygwin/10.0.0/../../.. /tmp/ccpwggue.o -lgcc_s -lgcc -lcygwin -ladvapi32 -lshell32 -luser32 -lkernel32 -lgcc_s -lgcc /lib/../lib/default-manifest.o /tmp/gcc-rust/usr/local/bin/../lib/gcc/x86_64-pc-cygwin/10.0.0/crtend.o
/usr/bin/ld: /lib/../lib/libcygwin.a(libcmain.o): in function `main':
/usr/src/debug/cygwin-3.1.4-1/winsup/cygwin/lib/libcmain.c:37: undefined reference to `WinMain'
/usr/src/debug/cygwin-3.1.4-1/winsup/cygwin/lib/libcmain.c:37:(.text.startup+0x7f): relocation truncated to fit: R_X86_64_PC32 against undefined symbol `WinMain'
collect2: error: ld returned 1 exit status
$ TMPDIR=/tmp /tmp/gcc-rust/usr/local/bin/gccrs.exe -c hello.rs
$ objdump -t hello.o | grep __main
$
This issue is related to 0378-expr-macros
However, it seems that macro_invoce!{x}
doesn't work for nightly rustc:
macro_rules! maybe_return { ($e:expr) => ($e); }
fn frob(x: i32) -> i32{
maybe_return! {x}
// should return -1
-1
}
The result is:
error[E0308]: mismatched types
--> ma.rs:4:20
|
4 | maybe_return! {x}
| ^- help: consider using a semicolon here
| |
| expected `()`, found `i32`
I may incorrectly understand the RFC description, anyway, I leave it here for a placeholder.
Our curent parser doesn't recogonize it too:
i32 frob(x : i32)
BlockExpr:
{
outer attributes: none
inner attributes: none
statements: none
final expression:
ArithmeticOrLogicalExpr: MacroInvocation: maybe_return!{x} - 1
}
Currently initializing struct members in StructExprFieldIndexValue and StructExprFieldIdentifierValue don't have any location info.
LiteralExpr need to be compiled as part of expressions etc.
Hi,
Is there a chance to see an update on the GCC Rust frontend? I’m uneasy seeing Rust tied solely to LLVM.
Best wishes,
Arne
First, it's not a hurry issue.
As I mentioned in another issue, gcc front-end is unnecessarily to be part of gcc source code, we can maintain gcc/rust as a standalone project, and users may make a link to gcc/rust so that gcc can detect it automatically.
If we do so, then we don't have to consider rebase upstream code anymore.
However, if we just remove redundant parts by git rm
, all the history is still kept in git database, and users will still clone the repo slowly. Not so perfect, but still better than keeping everything.
I've no idea about it, maybe we should ignore this issue at present?
Operations +, - etc need to be resolved and compiled to gimple
Please join forces with https://github.com/sapir/gcc-rust and don't try to do that by yourself. We need one good Rust frontend for GCC not multiple projects that both fail.
Thank you.
We need to support the size data type the array index expression code is using the i32 data type for the index but this should be size.
example:
int main(int argc, char **argv) {
int array[5] = {1,2,3,4,5};
int x = array[10];
return 0;
}
Compiling with GCC-master:
philbert@philbert-beast {~/workspace/gccrs-build} $ gcc -g -O0 -Wall test.c -o test
test.c: In function ‘main’:
test.c:4:9: warning: unused variable ‘x’ [-Wunused-variable]
4 | int x = array[10];
| ^
Compiling with clang:
philbert@philbert-beast {~/workspace/gccrs-build} $ clang -g -O0 -Wall test.c -o test
test.c:4:9: warning: unused variable 'x' [-Wunused-variable]
int x = array[10];
^
test.c:4:13: warning: array index 10 is past the end of the array (which contains 5 elements) [-Warray-bounds]
int x = array[10];
^ ~~
test.c:3:5: note: array 'array' declared here
int array[5] = {1,2,3,4,5};
^
2 warnings generated.
We need a name resolution dump to help with debugging:
To fully implement Hello World properly we need to finish all of macro expansion. Though we can hack a primitive implementation of println as an interim solution to help with added more useful test cases to progress other parts of the compiler.
We need to create a method to do name resolution and type basic type inferencing
I know it might have to be done on a separate project, but currently cargo will only use rustc
for dependencies and even use clang for C bindings (currently no way to compile C bindings using gcc).
gcc/rust/hir/tree/rust-hir-cond-compilation.h
from: #64 (comment)
This entire file is probably not required at the moment. The current implementation of the cfg attribute expansion just works with the Meta[InsertThingHere] data structures in the AST rather than using these separate configuration ones. As such, nothing would be converted to this HIR as nothing in the AST is stored in this manner.
Hi
This looks cool.
I only have a stupid question, really (apologies): can you mix up rust with openmp/openacc directives? Could you give an example?
Thanks!
This file is similar to the last one in that it should also be removed, for similar reasons. This was also a failed "first attempt" at an AST layout that should be unused in the current codebase.
Originally posted by @SimplyTheOther in #96 (comment)
Type resolution dumps will be critical in debugging the rust front-end. The format we have right now is pretty poor:
$ cat gccrs.type-resolution.dump
impl <Foo{0:Int:i32:(Ref: 60 TyRef: 8[8,26,])} HIRID: 35 RF:35 TF:129 - [28, ]> {
fn baz <fn (ref self & Foo{0:Int:i32:(Ref: 60 TyRef: 8[8,26,])},) -> () HIRID: 66 RF:66 TF:66 - []>
{
;
}
}
fn static_dispatch <fn<T REF: 70> (t & T REF: 70,) -> () HIRID: 81 RF:81 TF:81 - []>
{
;
}
fn dynamic_dispatch <fn (t & dyn [Bar],) -> () HIRID: 94 RF:122 TF:94 - [94, ]>
{
;
}
fn main <fn () -> () HIRID: 127 RF:127 TF:127 - []>
{
let a:<Foo{0:Int:i32:(Ref: 26 TyRef: 8[8,])} HIRID: 95 RF:100 TF:129 - [28, 95, 96, 98, 100, ]>;
a:<Foo{0:Int:i32:(Ref: 26 TyRef: 8[8,])} HIRID: 96 RF:100 TF:129 - [28, 95, 96, 98, 100, ]> = ;
;
let b:<& dyn [Bar] HIRID: 115 RF:116 TF:114 - [114, 116, 118, ]>;
b:<& dyn [Bar] HIRID: 116 RF:116 TF:114 - [114, ]> = ;
;
}
gccrs/gcc/rust/rust-session-manager.cc
Line 891 in 28f527c
We should be able to compile a function with variables and parameters down to gimple
8 | let c = xs[index + 1];
| ^
left denotation is null; returning null for parse_expr
The macro expansion happens before the resolution.
This issue is opened for the record of pipeline in kanban.
The current Rust compiler contains two IRs before GENERIC:
My previous experiences are more about functional programming language's compiler. That's relatively easier for coding, since there's pattern matching, and there're fewer side-effects (or even no) so that the optimizing is pretty easy: find the correct pattern, and inline the function or closure, then execute the rewriting rules. This process can cover many common optimizing, say, constant-fold, dead-variable-elimination, and dead-function-elimination, etc. For Rust, I think they're doing similar rewriting, but I need more researches.
The Rust compiler is written in Rust, so there's pattern matching. I guess we have to write more code for the tree node matching. After all, pattern matching is just syntax sugar, which expands more code that we have to write in C++.
I'm not sure if we can follow the exact design of HIR and MIR, since C++ may not be possible to cover the expressiveness exactly so that it's better to design a similar IR for taking advantage of C++ features. I'm just guessing, and I need more researches for the conclusion.
So I think the plan could be:
That's a rough plan, there're more things, including memory management, library interfaces, exceptions handling, etc. But I'm not sure where to put them in the pipeline. So I just listed them.
Comments?
Simple setup a system to convert AST to Backend types for GCC.
https://www.gnu.org/software/dejagnu/ needs added as a dep to the C++ CI workflow
When we are processing the HIR into gimple there is a crash when we call a function that has not been compiled yet.
let mut an_integer = 5;
an_integer = test(1) + 3;
let call_test = test(1);
}
fn test(x: i32) -> i32 {
return x + 1;
}
The resolution and type resolution correctly setup all mappings required to compile the main function and then compile the test function on request but there is a core in this code.
We should be able to compile structs such as:
one: i32,
two: i32,
}
fn main() {
let struct_test = Foo { one: 1, two: 2 };
}
When there is a statement such as:
let x = test(1);
This is parsed as:
Outer attributes: none
let x = outer attributes: none
StructExpr:
PathInExpr:
test(1)
inner attributes:none
I am unsure if this is intentional of not but we can work around this if its intended.
If macros are all expanded in the HIR, then this file should probably not exist. However, just in case they are needed, I would not remove the code here yet.
Originally posted by @SimplyTheOther in #64 (comment)
Assuming that (unexpanded) attributes and macros don't exist in the HIR, tokens shouldn't be required either, I don't think. The AST Token
is only used for storing the token data in macro invocations or attributes. Maybe a note of this could be made or something instead of actual deletion at this point, just in case it turns out that tokens are in fact needed.
Originally posted by @SimplyTheOther in #64 (comment)
We need to be able to compile if statements.
A declarative, efficient, and flexible JavaScript library for building user interfaces.
🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
An Open Source Machine Learning Framework for Everyone
The Web framework for perfectionists with deadlines.
A PHP framework for web artisans
Bring data to life with SVG, Canvas and HTML. 📊📈🎉
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
Some thing interesting about web. New door for the world.
A server is a program made to process requests and deliver data to clients.
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
Some thing interesting about visualization, use data art
Some thing interesting about game, make everyone happy.
We are working to build community through open source technology. NB: members must have two-factor auth.
Open source projects and samples from Microsoft.
Google ❤️ Open Source for everyone.
Alibaba Open Source for everyone
Data-Driven Documents codes.
China tencent open source team.