When record assertions fail, print an error message with the record's
location, so it's easier to see where the record that caused the assert
to fail was instantiated. This is useful when the assert condition in a
class depends on a template parameter, so we need to know the context of
the definition to determine why the assert failed.
Also enhanced the assert.td test to check for these context messages,
and also add checks for some assert failures that were missing in the
test.
Fix source location for anonymous records to be the one of the locations
where that record is instantiated as opposed to the location of the
class that was anonymously instantiated.
Currently, when a record is anonymously instantiated (via
`VarDefInit::instantiate`), we use the location of the class for the
record, which is not correct. Instead, pass in the `SMLoc` for the
location where the anonymous instantiation happens and use that location
when the record is instantiated. If there are multiple anonymous
instantiations with the same parameters, the location for the (single)
record created will be one of these instantiation locations as opposed
to the class location.
Add a !listflatten operator that will transform an input list of type
`list<list<X>>` to `list<X>` by concatenating elements of the
constituent lists of the input argument.
Don't call raw_string_ostream::flush(), which is essentially a no-op.
As specified in the docs, raw_string_ostream is always unbuffered.
( 65b13610a5226b84889b923bae884ba395ad084d for further reference )
Split RecordKeeper `getAllDerivedDefinitions` family of functions into
two variants:
(a) non-const ones that return vectors of `Record *` and
(b) const ones, that return vector/ArrayRef of `const Record *`.
This will help gradual migration of TableGen backends to use
`const RecordKeeper` and by implication change code to work
with const pointers and better const correctness.
Existing backends are not yet compatible with the const family of
functions, so change them to use a non-constant `RecordKeeper`
reference, till they are migrated.
`!getdagop` expects the dag operator to be a def, and errors out if it's
not.
While that's true in most cases, when multiclasses are involved, the
late resolution of the dag operator can result in it not being a def
yet, but still have a proper type, wich is required to check against the
optional parameter Ty in `!getdagop<Ty>`.
e.g, in the following dag:
```
(!cast<TestInstruction>(TestInstructionAndPattern::NAME) foo)
```
the operator is a UnOpInit, but all we need here is to check its type.
This fixes a bug where !getdagop is used to query the dag operator that
is dependent on the multiclass, which is not yet resolved to a def. Once
the folding is performed, the field becomes a record that can be
queried.
enum `RecordKind` is added to indicate the kind of Record (which
can be a normal record definition, anonymous record definition,
class or multiclass).
Some arguments like `IsMC` and `IsDefm` are removed since we can
get the information from `RecordKind`.
The keyword is intended for debugging purpose. It prints a message to
stderr.
This patch is based on code originally written by Adam Nemet, and on the
feedback received by the reviewers in
https://reviews.llvm.org/D157492.
The !repr operator represents the content of a variable or of a record
as a string.
This patch is based on code originally written by Adam Nemet, and on the
feedback received by the reviewers in
https://reviews.llvm.org/D157492.
We add a third argument `step` to `!range` bang operator to make it
with the same semantics as `range` in Python.
`step` can be negative. `step` is 1 by default and `step` can't be
0. If `start` < `end` and `step` is negative, or `start` > `end`
and `step` is positive, the result is an empty list.
We provide a way to specify arguments in the form of `name=value`
so that we don't have to specify all optional arguments before the
one we'd like to change. Required arguments can alse be specified
in this way.
Note that the argument can only be specified once regardless of
the way (named or positional) to specify and positional arguments
should be put before named arguments.
Reviewed By: reames
Differential Revision: https://reviews.llvm.org/D152998
A new Init type ArgumentInit is added to represent arguments. We currently only support positional arguments; an upcoming change will add named argument support.
The index of argument in error message is removed.
Differential Revision: https://reviews.llvm.org/D154066
- This patch proposes to add `!setdagarg` and `!setdagname` bang
operators to produce a new DAG node after replacing the specified
argument value/name from the given input DAG node. E.g.,
`!setdagarg((foo 1, 2), 0, "x")` produces `(foo "x", 2)` and
`!setdagname((foo 1:$a, 2:$b), 1, "c")` produces `(foo 1:$a, 2:$c)`.
Reviewed By: simon_tatham
Differential Revision: https://reviews.llvm.org/D151842
- This patch proposes to add `!getdagarg` and `!getdagname` bang
operators as the inverse operation of `!dag`. They allow us to examine
arguments of a given dag.
Reviewed By: simon_tatham
Differential Revision: https://reviews.llvm.org/D151602
This enables indexing in `!foreach` and permutation with `list[permlist]`.
Enhancements in syntax:
- `list<int>` is applicable as a slice element.
- `list[int,]` is evaluated as not `ElemType` but `list<ElemType>`
with a single element.
Part of D145872
FIXME: I didn't apply new semantics to BitSlice.
BitsRecTy objects are uniqued based on size. If the sizes are equal, then
the BitsRecTy objects are the same objects. We can use the base class
implementation that checks for pointer equality.
Since `RK::Recs` is sorted by character order, anonymous defs will be
enumerated like this;
- anonymous_0
- anonymous_1
- anonymous_10
- anonymous_100
- anonymous_1000
- ...
- anonymous_99
- anonymous_990
- ...
- anonymous_999
Some records around each gap might be wrapped around along increase or
decrease of records in middle. Then output order of anonymous defs
might be changed.
Numeric sort is expected to prevent such wrap-arounds.
This can be implemented with `StringRef::compare_numeric()`.
- ...
- anonymous_99
- anonymous_100
- ...
- anonymous_999
- anonymous_1000
- ...
See also discussions in D145874.
Differential Revision: https://reviews.llvm.org/D145874
This is a follow on to D145108. This started as simply fixing the crash on an error case reported against that change, but I think this also ends up fixing the original reported issue (https://github.com/llvm/llvm-project/issues/49830) as well. More accurately, D145108 fixed the case where the cast resolves to an existing record, and this change fixes the case where the named record doesn't exist.
Differential Revision: https://reviews.llvm.org/D145711
The core part of this change is an extension to the tablegen language to allow conditional definition of records using if-statements based on !exists conditions.
The RISCV td file change is mostly to illustrate the potential use of conditional definitions. I am deliberately not maximally simplifying in this change to make merging with downstream code (or simply rebasing while this on review) easier.
Some background to make the change understandable.
TableGen does not have an if statement internally. It has if expressions - in the form of TernInitOp with IF opcode - and foreach statements. It implements an if-statement as a foreach which iterates either 0 or 1 times.
Foreach nodes are then evaluated via unrolling inside the parser. Specifically, they are evaluated, at latest, when the outermost multiclass or loop containing them reaches end of scope. The unrolled statements remain (potentially) unresolved after unrolling, but the number of iterations must be known at this point.
An !exists clause can only evaluate at final evaluation. (Specifically, forward references to definitions are allowed - up to the end of the containing scope at least.) The existing code did not set the final flag on the resolver, and thus would leave the !exists clause in an unresolved state. This would then cause an error since we don't know how many iterations on which to unroll the (synthetic) foreach loop.
I chose to only finally-evaluate the condition of the if-expression. This allows us to pick an arm at scope exit without inhibiting definitions in the arm from having self references.
Differential Revision: https://reviews.llvm.org/D145108
Use deduction guides instead of helper functions.
The only non-automatic changes have been:
1. ArrayRef(some_uint8_pointer, 0) needs to be changed into ArrayRef(some_uint8_pointer, (size_t)0) to avoid an ambiguous call with ArrayRef((uint8_t*), (uint8_t*))
2. CVSymbol sym(makeArrayRef(symStorage)); needed to be rewritten as CVSymbol sym{ArrayRef(symStorage)}; otherwise the compiler is confused and thinks we have a (bad) function prototype. There was a few similar situation across the codebase.
3. ADL doesn't seem to work the same for deduction-guides and functions, so at some point the llvm namespace must be explicitly stated.
4. The "reference mode" of makeArrayRef(ArrayRef<T> &) that acts as no-op is not supported (a constructor cannot achieve that).
Per reviewers' comment, some useless makeArrayRef have been removed in the process.
This is a follow-up to https://reviews.llvm.org/D140896 that introduced
the deduction guides.
Differential Revision: https://reviews.llvm.org/D140955
value() has undesired exception checking semantics and calls
__throw_bad_optional_access in libc++. Moreover, the API is unavailable without
_LIBCPP_NO_EXCEPTIONS on older Mach-O platforms (see
_LIBCPP_AVAILABILITY_BAD_OPTIONAL_ACCESS).
This commit fixes LLVMAnalysis and its dependencies.