998: Parse macro expansion properly r=CohenArthur a=CohenArthur
This PR adds a base for trying to parse statements or items in macro invocations. We are now able to parse multiple items / expressions / statements properly, but do not lower them properly, which is the last remaining task in #943
New macro parsing logic:
```mermaid
flowchart TD;
has_semi -- Yes --> stmt;
has_semi -- No --> invocation;
invocation -- Is Parens --> expr;
invocation -- Is Square --> expr;
invocation -- Is Curly --> stmt;
```
Closes#943Closes#959Closes#952
Co-authored-by: Arthur Cohen <arthur.cohen@embecosm.com>
Different parsing functions need to be called based on the context
surrounding the macro invocation. This commit adds a flowchart trying to
explain the base resolving rules
Macro expansion happens at the same level as stripping, where nodes
might get removed if they are gated behind an unmet predicate. We also
perform macro expansion during this visitor's pass.
What we can do is thus to replace macro invocations with new items that
might have resulted from macro expansion: Since we're already mutating
numerous elements by removing them if they should be stripped, we can
also add elements if they should be expanded.
This commit also "fixes" macro test cases so that they are now accepted
by the new parser, which is more strict than it should for now.
Co-authored-by: SimplyTheOther <simplytheother@gmail.com>
Co-authored-by: philberty <philip.herron@embecosm.com>
Adds an extra layer of abstraction around keeping multiple matches for
the same fragment. This avoids ugly code fetching the first match in
order to get the amounf of matches given by the user, while still
allowing zero-matches to exist.
Co-authored-by: philberty <philip.herron@embecosm.com>
Slices and Arrays are covariant types which means they can contain elements
which bind generics such as ADT or FnTypes. This means substitutions can be
recursive and this gives the typechecker a chance to handle this recursion
on these types.
When we intercept impl blocks for slices or raw pointers we must generate
the canonical path for this for name resolution this adds in the missing
visitors which will generate the path. Previously this was defaulting to
empty path segments and then hitting an assertion when we append the
empty segment.
Fixes#1005
This is another type of intrisic since the function contains no parameters
but the argument for the size_of is the generic parameter T. Which uses
TYPE_SIZE_UNIT to get the type size in bytes. GCC will optimize the
function call away when you turn optimizations on.
Addresses #658
Intrinsics were hidden behind the GCC abstract. This removes it by keeping
all of this logic within rust-intrinsic.cc so that we can make mappings of
the rustc name to GCC ones. We have a big comment from the mappings used
over to LLVM builtins which we can use to help guide how we do this for
GCC.
This patch adds the initial support for generic intrinsics these are do not
map directly to GCC builtins and need to be substited with their specificed
types. This patch allows for custom implementation body for these functions
by specifying handler functions which will generate the applicable
intrinsic when asked for.
Addresses #658
999: Refactor ABI options as part of HIR function qualifiers r=philberty a=philberty
This is a refactor to cleanup HIR::ExternBlock and HIR::FunctionQualifiers
to have an enum of ABI options to improve the error handling.
Co-authored-by: Philip Herron <philip.herron@embecosm.com>
994: Parse macro patterns properly in repetitions r=CohenArthur a=CohenArthur
Closes#966
We actually cannot reuse functions from the parser since we're expanding a macro transcriber. This is fine as the "algorithm" is extremely simple
997: macros: Allow any delimiters for invocation r=CohenArthur a=CohenArthur
Closes#946
Co-authored-by: Arthur Cohen <arthur.cohen@embecosm.com>
The AST has an ABI string as part of the function qualifiers, this was the
same in the HIR as it was initially a copy-paste. This patch changes the
HIR function qualifiers to have an enum of ABI options, during HIR lowering
the enum is setup and if an unknown ABI option is specified an error is
emitted.
It is not necessary for macro invocations to match the delimiters used
in the matcher. A matcher using parentheses can be invoked with curlies
or brackets, as well as any other combination(curlies matcher can be
invoked with parentheses or brackets)
992: Cleanup bad unused code warnings r=philberty a=philberty
This patchset contains 4 distinct fixes:
When a constant is declared after where it is used the code-generation pass falls
back to a query compilation of the HIR::Item this did not contain a check to verify
if it was already compiled and results in duplicate CONST_DECLS being generated
if query compilation was used.
We were using a zero precision integer to contain unit-type expressions this results
in VAR_DECLS being lost in the GENERIC graph which does not allow us to perform
any static analysis upon the DECL. This changes the unit type to use an empty struct
and for initialization of a VAR_DECL we can simply pass an empty constructor and let
GCC optimize this code for us.
Update our DEAD_CODE scan to take into account modules of items and also respect
if structures are prefixed with an underscore we can ignore generating an unused warning.
Remove our AST scan for unused code and reuse GCC TREE_USED to track wether
VAR_DECL, PARM_DECL, CONST_DECL are actually used or not. We reuse the GCC
walk_tree functions to have this as nice separate lint.
Fixes#676
Co-authored-by: Philip Herron <philip.herron@embecosm.com>
This now uses the TREE_USED fields on GCC tree's to track the usage of
VAR_DECLS, PARM_DECLS and CONST_DECLS. The code does a pass over the body
and parameters of functions as a lint pass.
Fixes#676
991: Match and expand macro separators properly r=CohenArthur a=CohenArthur
More nice recursive macros:
```rust
macro_rules! add {
($e:expr | $($es:expr) | *) => {
$e + add!($($es) | *)
};
($e:expr) => {
$e
};
}
add!(1 | 2 | 3 | 4 | 5 | 6);
```
Closes#968
This PR needs #986 to be merged first, as it depends on it for the test cases. You can skip reviewing the first two commits which are just from #986
Co-authored-by: Arthur Cohen <arthur.cohen@embecosm.com>
986: Fix ICE on recursive macro invocation r=CohenArthur a=CohenArthur
Closes#982
We can now do fancy lispy things!
```rust
macro_rules! add {
($e:literal) => {
0 + $e
};
($e:literal $($es:literal)*) => {
$e + add!($($es)*)
};
}
```
I've switched the order of the commits around so that the buildbot is happy
Co-authored-by: Arthur Cohen <arthur.cohen@embecosm.com>
985: Parse macro!(); as MacroInvocation with semicolon r=CohenArthur a=CohenArthur
When parsing a macro invocation as a statement, the parser would parse
an expression and then try parsing a semicolon. Since no actual
lookahead was done (which is a good thing), we couldn't convert a
`MacroInvocation` to a `MacroInvocationSemi` after the fact.
Since, unlike function calls, macro invocations can act differently
based on whether or not they are followed by a semicolon, we actually
need to differentiate between the two up until expansion.
This commits adds a new virtual method for ExprWithoutBlock when
converting to ExprStmtWithoutBlock so that classes inheriting
ExprWithoutBlock can specify a new behavior. In the case of our
MacroInvocation class, it simply means toggling a boolean: If we're
converting a macro from an expression to a statement, it must mean that
it should contain a semicolon.
Closes#941
Co-authored-by: Arthur Cohen <arthur.cohen@embecosm.com>
990: Add must use attribute support r=philberty a=philberty
This is a port of the CPP front-end nodiscard attribute to be used for
must_use. It contains a patch to clean up how we handle expressions vs
statements and removes more of the GCC abstraction. Its my hope that we
can leverage more and more existing code to get the static analysis where
we want it.
Fixes#856
Co-authored-by: Philip Herron <philip.herron@embecosm.com>
984: Implimented Soluion 1 and solution 2 for issue_734 r=philberty a=mvvsmk
Fixes#734
Done :
- [x] Remove iterate_params function
- [x] Create new get_params function
Solution 1
1) Created a new get_params function which returns the parameters.
2) Changed the references of the iterate_params to use get_params.
Solution 2
1) Added get_params2 which returns `std::vector<TyTy::BaseType*>`
2) Changed the references of the iterate_params to use get_params.
Status :
Currently I have implemented the first solution.
Signed-off-by : M V V S Manoj Kumar <mvvsmanojkumar@gmail.com>
Co-authored-by: M V V S Manoj Kumar <mvvsmanojkumar@gmail.com>
Fixes issue #734
1)Removed iterate_params function
2)Created a get_params function which returns std::vector& params
Signed-off-by : M V V S Manoj Kumar <mvvsmanojkumar@gmail.com>
When creating a sub-map for repetitions, we need to be weary of not
accessing matched-fragments beyond the vector's size. For example, with
the following *fragments*
{ "e": [1], "es": [2, 3, 10]},
the sub-maps we want to create are the following:
{ "e": [1], "es": [2]},
{ "e": [1], "es": [3]},
{ "e": [1], "es": [10]},
Up until this point however, we were trying to access the second index
for the "e" metavar when creating the second submap, then the third, and
so on... which is obviously outside of the vector's bounds.
We can simply check if the metavar only has one match and expand that
one in that case. We still need to work on checking that multiple
metavars in the same transcriber repetition pattern have the same amount
of matched fragments (ie the original vectors of matches in the
original map have the same size)
This ports over the code from the cpp front-end which implements the cpp
nodiscard attribute which has the same behaviour and is also implemented
in the front-end explicitly.
Fixes#856
The gcc abstraction contained a method of turning expressions into
statements which used to contain their own types like Bstatement,
Bexpression this produced awkward interfaces which we no longer require.
This is part of a patch series to introduce the CPP front-end
convert_to_void to port over the support for the nodiscard attribute which
maps nicely over to Rust's must_use attribute.
Fixes the -fself-test invalid memory accesses and adds documentation
regarding a possible future fix.
Co-authored-by: tschwinge <thomas@schwinge.name>
Co-authored-by: philberty <philip.herron@embecosm.com>
When creating a sub-map for repetitions, we need to be weary of not
accessing matched-fragments beyond the vector's size. For example, with
the following *fragments*
{ "e": [1], "es": [2, 3, 10]},
the sub-maps we want to create are the following:
{ "e": [1], "es": [2]},
{ "e": [1], "es": [3]},
{ "e": [1], "es": [10]},
Up until this point however, we were trying to access the second index
for the "e" metavar when creating the second submap, then the third, and
so on... which is obviously outside of the vector's bounds.
We can simply check if the metavar only has one match and expand that
one in that case. We still need to work on checking that multiple
metavars in the same transcriber repetition pattern have the same amount
of matched fragments (ie the original vectors of matches in the
original map have the same size)
981: macro-expand: Add SubstitutionCtx class in its own file r=CohenArthur a=CohenArthur
The `MacroExpander` class had multiple static functions which were constantly passing the same parameters around for expansion. This refactor adds a new `SubstituteCtx` class which keeps track of the three common arguments given to the substitute functions, and offers these implementations in a new source file to keep the original expander light.
Closes#957
Co-authored-by: Arthur Cohen <arthur.cohen@embecosm.com>
When parsing a macro invocation as a statement, the parser would parse
an expression and then try parsing a semicolon. Since no actual
lookahead was done (which is a good thing), we couldn't convert a
`MacroInvocation` to a `MacroInvocationSemi` after the fact.
Since, unlike function calls, macro invocations can act differently
based on whether or not they are followed by a semicolon, we actually
need to differentiate between the two up until expansion.
This commits adds a new virtual method for ExprWithoutBlock when
converting to ExprStmtWithoutBlock so that classes inheriting
ExprWithoutBlock can specify a new behavior. In the case of our
MacroInvocation class, it simply means toggling a boolean: If we're
converting a macro from an expression to a statement, it must mean that
it should contain a semicolon.
In order to conform to the rust reference, we must make sure that when
parsing -frust-cfg key-value pairs, we actually parse a valid key and
value. The key must be a valid identifier, while the value must be a
valid identifier surrounded by double quotes
By allowing us to parse strings directly instead of necessarily a
filename, we are now able to reuse the parser and lexer in various
places of the compiler. This is useful for -frust-cfg, but may also come
in handy for
other compiler mechanics such as the include!() builtin macro, where we
do not actually want location info but just a stream of tokens.