aboutsummaryrefslogtreecommitdiffstatshomepage
AgeCommit message (Collapse)AuthorFilesLines
2022-06-27bitwise: early expansion of simple constantsbitwise-onesLuc Van Oostenryck3-2/+60
C has only positive constants: -1 is really an expression, the unary '-' operator applied to the constant 1. '-1' as a constant value only exists after the expansion of constant expressions. This is rather unfortunate since it inhibits easy testing of such constants in the evaluation phase, like here for restricted_value(). So, expand expressions like +CTE, -CTE or ~CTE before calling restricted_value(). Signed-off-by: Luc Van Oostenryck <luc.vanoostenryck@gmail.com>
2022-06-27bitwise: do not remove the signedness of bitwise typesLuc Van Oostenryck3-3/+1
When bitwise types were added [1] the signedness modifiers were removed from them. More exactly, it was MOD_SPECIFIER which was removed. I suppose this was done because then MOD_SPECIFIER contained the signedness bits but also MOD_CHAR, MOD_LONG, ... and those had to be removed. But currently MOD_SPECIFIER contains only MOD_SIGNEDNESS and the signedness info can be useful for bitwise types too. So, do not removed anymore MOD_SPECIFIER from the bitwise types' modifiers. [1] commit 032f492af0ac ("[PATCH] __attribute__((bitwise))") Signed-off-by: Luc Van Oostenryck <luc.vanoostenryck@gmail.com>
2022-06-27bitwise: allow compares for bitwise typesLuc Van Oostenryck3-2/+4
Currently, bitwise types are restricted to bitwise operations (&, |, ^ and ~) as well as equality comparisons. This patch makes the others comparisons valid for bitwise types too. Warning: This change make sense in the context of [1] but doesn't make sense for the 'main' bitwise types: __be32 and friends. Signed-off-by: Luc Van Oostenryck <luc.vanoostenryck@gmail.com>
2022-06-27bitwise: accept all ones as non-restricted valueLuc Van Oostenryck2-1/+14
Currently, the only value bitwise types can act on is 0 because the this value is anyway invariant for all bitwise operations and endianness conversions. But, a bit-pattern of all ones has the same properties and is also very often used. So, accept all ones as a valid value for bitwise operations. Signed-off-by: Luc Van Oostenryck <luc.vanoostenryck@gmail.com>
2022-06-27bitwise: add testcasesLuc Van Oostenryck4-0/+90
Currently bitwise types only support bitwise operations (&, |, ^ and ~) and the constant 0 (since this value is invariant for all bitwise operations and endianness conversion). But the incoming series will relax this a little bit. So, add a few testcases for it. Signed-off-by: Luc Van Oostenryck <luc.vanoostenryck@gmail.com>
2022-06-14predefine __ATOMIC_ACQUIRE & friends as weakLuc Van Oostenryck1-6/+6
In kernel's arch/mips/Makefile the whole content of gcc's -dM is used for CHECKFLAGS. This conflict with some macros also defined internally: builtin:1:9: warning: preprocessor token __ATOMIC_ACQUIRE redefined builtin:0:0: this was the original definition Fix this by using a weak define for these macros. Reported-by: Randy Dunlap <rdunlap@infradead.org> Reported-by: kernel test robot <lkp@intel.com> Signed-off-by: Luc Van Oostenryck <luc.vanoostenryck@gmail.com>
2022-06-09Merge branches 'cgcc-dash-x' and 'fixes'Luc Van Oostenryck3-0/+19
* cgcc: do not die on '-x assembler' * fix crash when inlining casts of erroneous expressions - allow show_token() on TOKEN_ZERO_IDENT
2022-06-09allow show_token() on TOKEN_ZERO_IDENTLuc Van Oostenryck1-0/+2
TOKEN_ZERO_IDENTs are created during the evaluation of pre-processor expressions but which otherwise are normal idents and were first tokenized as TOKEN_IDENTs. As such, they could perfectly be displayed by show_token() but are not. So, in error messages they are displayed as "unhandled token type '4'", which is not at all informative. Fix this by letting show_token() process them like usual TOKEN_IDENTs. Idem for quote_token(). Signed-off-by: Luc Van Oostenryck <luc.vanoostenryck@gmail.com> Acked-by: Linus Torvalds <torvalds@linux-foundation.org>
2022-06-07fix crash when inlining casts of erroneous expressionsLuc Van Oostenryck2-0/+17
Sparse do inlining very early, during expansion, just after (type) evaluation and before IR linearization, and is done even if some errors have been found. This means that the inlining must be robust against erroneous code. However, during inlining, a cast expression is always dereferenced and a crash will occur if not valid (in which case it should be null). Fix this by checking for null cast expressions and directly returning NULL, like done for the inlining of the other invalid expressions. Link: https://lore.kernel.org/r/e42698a9-494c-619f-ac16-8ffe2c87e04e@intel.com Reported-by: kernel test robot <lkp@intel.com> Reported-by: Yafang Shao <laoar.shao@gmail.com> Reported-by: Yujie Liu <yujie.liu@intel.com> Signed-off-by: Luc Van Oostenryck <luc.vanoostenryck@gmail.com>
2022-06-06cgcc: do not die on '-x assembler'Luc Van Oostenryck1-3/+2
Currently cgcc will die if the option '-x' is used with any argument other than 'c'. It makes sense since sparse can only handle C files but it can be useful in a project to simply use something like: make CC=cgcc So, instead of die()ing, avoid calling sparse if such '-x' option is used, like already done by default for non .c files. Original-patch-by: Tom Rix <trix@redhat.com> Signed-off-by: Luc Van Oostenryck <luc.vanoostenryck@gmail.com>
2022-06-05Merge branch 'riscv'Luc Van Oostenryck1-13/+9
* riscv: small improvements of '-march' parsing
2022-06-05RISC-V: Remove "g" from the extension listPalmer Dabbelt1-1/+0
"g" goes along with the base ISA, but it was being treated as an extension. This allows for all sorts of odd ISA strings to be accepted by sparse, things like "rv32ig" or "rv32gg". We're still allowing some oddities, like "rv32ga", but this one was easy to catch. Signed-off-by: Palmer Dabbelt <palmer@rivosinc.com> Signed-off-by: Luc Van Oostenryck <luc.vanoostenryck@gmail.com>
2022-06-05RISC-V: Remove the unimplemented ISA extensionsPalmer Dabbelt1-10/+0
This made sense when we die()d on unknown ISA extensions, but now that we're just warning it's actually a bit detrimental: users won't see that their unimplemented ISA extensions are silently having the wrong definitions set, which may cause hard to debug failures. Signed-off-by: Palmer Dabbelt <palmer@rivosinc.com> Signed-off-by: Luc Van Oostenryck <luc.vanoostenryck@gmail.com>
2022-06-05RISC-V: Match GCC's semantics for multiple -march instancesPalmer Dabbelt1-0/+3
GCC's semantics for "-march=X -march=Y" are that Y entirely overrides X, but sparse takes the union of these two ISA strings. This fixes the behavior by setting, instead of oring, the flags whenever a base ISA is encountered. RISC-V ISA strings can only have a single base ISA, it's not like x86 where the 64-bit ISA is an extension of the 32-bit ISA. [Luc Van Oostenryck: reset the flags at the start of the parsing loop] Signed-off-by: Palmer Dabbelt <palmer@rivosinc.com> Signed-off-by: Luc Van Oostenryck <luc.vanoostenryck@gmail.com>
2022-06-05RISC-V: don't die() on -march errors, just warnPalmer Dabbelt1-2/+6
Parsing RISC-V ISA strings is extremely complicated: there are many extensions, versions of extensions, versions of the ISA string rules, and a bunch of unwritten rules to deal with all the bugs that fell out of that complexity. Rather than die()ing when the ISA string parsing fails, just stop parsing where we get lost and emit a warning. Changes tend to end up at the end of the ISA string, so that's probably going to work (and if it doesn't there's a warning to true and clue folks in). This does have the oddity in that "-Wsparse-error" is ignored for this warning but this option was never meant to be used at this stage of the processing.. [Luc Van Oostenryck: drop handling of "-Wsparse-error"] Suggested-by: Linus Torvalds <torvalds@linux-foundation.org> Based-on-patch-by: Palmer Dabbelt <palmer@rivosinc.com> Signed-off-by: Luc Van Oostenryck <luc.vanoostenryck@gmail.com>
2022-06-05Merge branch 'cast-value'Luc Van Oostenryck4-9/+10
* small improvements to cast_value()
2022-05-31cast_value: remove error-prone redundant argumentLuc Van Oostenryck4-7/+6
The last two arguments of cast_value() are the old expression and the oldtype which suggest that this oldtype can be distinct from the type of the old expression. But this is not the case because internally the type used to retrieve the value of the expression is the type of the expression itself (old->ctype) the type which is used and the two types must be the same (or at least be equivalent). So, remove the error-prone last argument and always us the type of the expression itself. Signed-off-by: Luc Van Oostenryck <luc.vanoostenryck@gmail.com>
2022-05-31cast_value: assign the new typeLuc Van Oostenryck3-2/+4
The first two arguments of cast_value() are the new expression and the type wanted for it. This type is then used to calculate the new value. But the type of the expression must be assigned separately (usually after the cast because the old and the new expression can refer to the same object). To avoid any possible inconsistencies, assign the new type during the casting itself. Signed-off-by: Luc Van Oostenryck <luc.vanoostenryck@gmail.com>
2022-05-31Merge branch 'fixes' into masterLuc Van Oostenryck6-1/+59
* fix zero/sign extension of integer character constants * handle clang's option "-meabi gnu" * fix infinite loop when expanding __builtin_object_size() with self-init vars
2022-05-31fix zero/sign extension of integer character constantsLuc Van Oostenryck3-1/+27
An integer character constant has type 'int' but, subtly enough, its value is the one of a 'char' converted to an 'int'. So, do this conversion. Also set the type of wide character constants from 'long' to 'wchar_t'. Link: https://lore.kernel.org/r/20210927130253.GH2083@kadam Reported-by: Dan Carpenter <dan.carpenter@oracle.com> Reported-by: Rasmus Villemoes <linux@rasmusvillemoes.dk> Signed-off-by: Luc Van Oostenryck <luc.vanoostenryck@gmail.com>
2022-05-22Merge branch 'xtensa'Luc Van Oostenryck1-0/+7
* cgcc: add Xtensa support
2022-05-22cgcc: add Xtensa supportGuennadi Liakhovetski1-0/+7
Add support for the Xtensa architecture. Signed-off-by: Guennadi Liakhovetski <guennadi.liakhovetski@linux.intel.com> Signed-off-by: Luc Van Oostenryck <luc.vanoostenryck@gmail.com>
2022-05-22handle clang's option "-meabi gnu"Luc Van Oostenryck1-0/+13
Clang has an option "-meabi <arg>" which is used by the kernel for ARMv7. This kind of option, taking a argument without a separating '=', can't be ignored like most other options and must this be special-cased. So, add the special case for this option and consume the argument if it's one of the valid one. Link: https://lore.kernel.org/r/20220331110118.vr4miyyytqlssjoi@pengutronix.de Reported-by: Marc Kleine-Budde <mkl@pengutronix.de> Signed-off-by: Luc Van Oostenryck <luc.vanoostenryck@gmail.com>
2022-05-21Merge branch 'riscv-zicsr'Luc Van Oostenryck1-2/+10
* riscv: add the Zicsr extension * riscv: add the Zifencei extension
2022-05-21RISC-V: Add the Zifencei extensionPalmer Dabbelt1-0/+4
Recent versions of binutils default to an ISA spec version that doesn't include Zifencei as part of I, so Linux has recently started passing this in -march. [ Luc Van Oostenryck: move this patch at the start of the series ] Signed-off-by: Palmer Dabbelt <palmer@rivosinc.com> Signed-off-by: Luc Van Oostenryck <luc.vanoostenryck@gmail.com>
2022-05-21RISC-V: Add the Zicsr extensionPalmer Dabbelt1-2/+6
Recent versions of binutils default to an ISA spec version that doesn't include Zicsr as part of I, so Linux has recently started passing this in -march. [ Luc Van Oostenryck: move this patch at the start of the series ] Signed-off-by: Palmer Dabbelt <palmer@rivosinc.com> Signed-off-by: Luc Van Oostenryck <luc.vanoostenryck@gmail.com>
2022-05-21Use offsetof macro to silence null ptr subtraction warningRichard Palethorpe1-1/+1
Subtracting (char *)0 is undefined behavior. Newer compilers warn about this unless it is done in system headers. Signed-off-by: Richard Palethorpe <rpalethorpe@suse.com> Signed-off-by: Luc Van Oostenryck <luc.vanoostenryck@gmail.com>
2022-05-21fix one year off in v0.6.4's release notesLuc Van Oostenryck1-1/+1
Bernhard Voelker noticed that the date in the release notes is one year off. Fix this. Reported-by: Bernhard Voelker <mail@bernhard-voelker.de> Signed-off-by: Luc Van Oostenryck <luc.vanoostenryck@gmail.com>
2022-05-21Merge branch 'semid'Luc Van Oostenryck5-2/+72
* semind: Index more symbols For indexing purposes, macros definitions and typedefs are added to the semind database. Functions that are not used in the code are also indexed. Signed-off-by: Luc Van Oostenryck <luc.vanoostenryck@gmail.com>
2022-05-21Merge branch 'next-ramsay'Luc Van Oostenryck4-1/+56
* fix regression disabling the 'memcpy-max-count' check. * warn about a 'case label' on empty statement Signed-off-by: Luc Van Oostenryck <luc.vanoostenryck@gmail.com>
2022-05-21dissect: Show typedefsAlexey Gladkov2-1/+14
For indexing purposes, it is useful to see type definitions. $ semind search __kernel_ulong_t (def) include/uapi/asm-generic/posix_types.h 16 23 typedef unsigned long __kernel_ulong_t; Signed-off-by: Alexey Gladkov <gladkov.alexey@gmail.com> Signed-off-by: Luc Van Oostenryck <luc.vanoostenryck@gmail.com>
2022-05-21dissect: Show macro definitionsAlexey Gladkov2-2/+14
Add the ability to dissect to see macro definitions. The patch does not add full support for the usage of macros, but only their definitions. Signed-off-by: Alexey Gladkov <gladkov.alexey@gmail.com> Signed-off-by: Luc Van Oostenryck <luc.vanoostenryck@gmail.com>
2022-05-21dissect: Allow to show all symbolsAlexey Gladkov4-1/+46
Currently dissect sees only used symbols. For indexing purposes, it is useful to see all declared symbols. $ nl -s\ -w2 ./z.c 1 struct foo { 2 int member; 3 }; 4 #ifdef OPT 5 static void func1(void) { 6 struct foo *x; 7 return 0; 8 } 9 #endif 10 static inline void func2(void) { return; } 11 void func(void) { return; } $ ./test-dissect ./z.c FILE: ./z.c 11:6 def f func void ( ... ) $ ./test-dissect --param=dissect-show-all-symbols ./z.c FILE: ./z.c 1:8 def s foo struct foo 2:13 def m foo.member int 10:20 def f func2 void ( ... ) 11:6 def f func void ( ... ) Signed-off-by: Alexey Gladkov <gladkov.alexey@gmail.com> Signed-off-by: Luc Van Oostenryck <luc.vanoostenryck@gmail.com>
2022-05-21fix infinite loop when expanding __builtin_object_size() with self-init varsLuc Van Oostenryck2-0/+19
expand_object_size(), used to expand __builtin_object_size(), recursively try to get the parent initializer. This fails miserably by looping endlessly when the object is a self-initialized variable. For the moment, fix this in the most obvious way: stop the recursion and do not expand such variables. Note: I wouldn't be surprised if these self-initialized variables create other problems elsewhere. Maybe we should remove their initializer and somehow mark them as "do not warn about -Wuninitialized" (well, there is no such warnings *yet*). Signed-off-by: Luc Van Oostenryck <luc.vanoostenryck@gmail.com>
2022-05-20parse: warn about a 'case label' on empty statementRamsay Jones2-0/+27
Commit 0d6bb7e1 ("handle more graciously labels with no statement", 2020-10-26) allowed a label to appear just before the closing brace of a compound statement. This is not valid C (which would require at least a null statement). Similarly, a case label is also not allowed to appear just before a closing brace. So, extend the solution of commit 0d6bb7e1 to issue a warning for case labels and 'insert' a null statement. Note that the next C standard (C23 ?) will allow even more freedom in the placement of labels (see N2508 [1]) and make this placement (along with others) legal C. [1] https://www9.open-std.org/JTC1/SC22/WG14/www/docs/n2508.pdf Signed-off-by: Ramsay Jones <ramsay@ramsayjones.plus.com> Signed-off-by: Luc Van Oostenryck <luc.vanoostenryck@gmail.com>
2022-05-20sparse: fix broken 'memcpy-max-count' checkRamsay Jones2-1/+29
commit a69f8d70 ("ptrlist: use ptr_list_nth() instead of linearize_ptr_\ list()", 2021-02-14) replaced a call to a local helper with a more generic ptr_list function. The local function, argument(), was used to retrieve the 'argno' argument to a function call, counting the arguments from one. This call was replaced by the generic ptr_list_nth() function, which accessed the ptr_list counting from zero. The 'argno' passed to the call to argument() was 3 (the byte count), which when passed to ptr_list_nth() was attempting to access the 4th (non-existent) argument. (The resulting null pointer was then passed to check_byte_count() function, which had an null-pointer check and so did not dereference the null pointer). This effectively disabled the memcpy-max-count check. In order to fix the check, change the 'argno' of 3 to the 'index' of 2. Also, add a simple regression test. Signed-off-by: Ramsay Jones <ramsay@ramsayjones.plus.com> Signed-off-by: Luc Van Oostenryck <luc.vanoostenryck@gmail.com>
2021-09-06Sparse v0.6.4v0.6.4Luc Van Oostenryck2-3/+3
Signed-off-by: Luc Van Oostenryck <luc.vanoostenryck@gmail.com>
2021-09-01Sparse v0.6.4-rc1v0.6.4-rc1Luc Van Oostenryck1-1/+1
2021-09-01Add release notes for incoming v0.6.4Luc Van Oostenryck2-0/+106
Signed-off-by: Luc Van Oostenryck <luc.vanoostenryck@gmail.com>
2021-08-02Merge branch 'schecker-fixes'Luc Van Oostenryck1-17/+31
* small fixes for the symbolic checker
2021-07-29scheck: fix type of operands in castsLuc Van Oostenryck1-10/+8
Casts were using the target type for their operands. Fix this by using the new helper mkivar() for them. Signed-off-by: Luc Van Oostenryck <luc.vanoostenryck@gmail.com>
2021-07-27scheck: mkvar() with target or input typeLuc Van Oostenryck1-0/+12
Most instructions have one associated type, the 'target type'. Some, like compares, have another one too, the 'input type'. So, when creating a bitvector from an instruction, we need to specify the type in some way. So, create an helper for both cases: mktvar() and mkivar(). Signed-off-by: Luc Van Oostenryck <luc.vanoostenryck@gmail.com>
2021-07-27scheck: constants are untypedLuc Van Oostenryck1-3/+2
in sparse, constants (PSEUDO_VALs) are not typed, so the same pseudo can be used to represent 1-bit 0, 8-bit 0, 16-bit 0, ... That's incompatible with the bit vectors used here, so we can't associate a PSEUDO_VAL with its own bitvector like it's done for PSEUDO_REGs. A fresh one is needed for each occurrence (we could use a small table but won't bother). Signed-off-by: Luc Van Oostenryck <luc.vanoostenryck@gmail.com>
2021-07-27scheck: ignore OP_NOP & friendsLuc Van Oostenryck1-0/+5
Some instructions have no effects and so can just be ignored here. Signed-off-by: Luc Van Oostenryck <luc.vanoostenryck@gmail.com>
2021-07-27scheck: better diagnostic for unsupported instructionsLuc Van Oostenryck1-4/+4
When reporting an unsupported instruction, display the instruction together with the diagnostic message. Signed-off-by: Luc Van Oostenryck <luc.vanoostenryck@gmail.com>
2021-07-27fix missing itype in SEL(x, 0/1, 1/0) --> (x ==/!= 0)Luc Van Oostenryck1-0/+1
Since commit 226b62bc2ee4 ("eval_insn: give an explicit type to compare's operands") it's needed to set the operands' type of every compare instructions but it was missing in this case where a select is transformed into a compare. So, add the missing type. Signed-off-by: Luc Van Oostenryck <luc.vanoostenryck@gmail.com>
2021-04-20Merge branches misc, cmp-pow2, optim-and-cmp, cmp-and-or and optim-cast-eval ↵Luc Van Oostenryck11-74/+243
into next * no needs to use MARK_CURRENT_DELETED() for multi-jumps * canonicalize ((x & M) == M) --> ((x & M) != 0) when M is a power-of-2 * simplify AND(x >= 0, x < C) --> (unsigned)x < C * simplify TRUNC(x) {==,!=} C --> AND(x,M) {==,!=} C * remove early simplification of casts during evaluation * but this back as simplificaion of TRUNC(NOT(x)) --> NOT(TRUNC(x))
2021-04-19remove early simplification of casts during evaluationLuc Van Oostenryck3-45/+1
The current code will simplify away some casts at evaluation time but doesn't take in account some special cases: * (bool)~<int> is not equivalent to ~(bool)<int> (anything not all 0 or 1) * (float)~<int> is not equivalent to ~(float)<int> which doesn't make sense. * (int)(float)<int> is not a no-op if the (float) overflows This kind of simplification is better done on the IR where the different kind of casts correspond to distinct instructions. Signed-off-by: Luc Van Oostenryck <luc.vanoostenryck@gmail.com>
2021-04-19simplify TRUNC(NOT(x)) --> NOT(TRUNC(x))Luc Van Oostenryck2-1/+15
The goal is double: 1) be able to do the NOT operation on the smaller type 2) more importantly, give the opportunity to the TRUNC to cancel with a previous ZEXT if there is one. Signed-off-by: Luc Van Oostenryck <luc.vanoostenryck@gmail.com>
2021-04-18TRUNC(x) {==,!=} C --> AND(x,M) {==,!=} CLuc Van Oostenryck1-0/+14
It's not 100% clear than this is indeed a simplification but: 1) from a pure instruction count point of view, it doesn't make things worst 2) in most place where it applies, the masking is made redundant and is thus eliminated Signed-off-by: Luc Van Oostenryck <luc.vanoostenryck@gmail.com>
2021-04-18simplify AND(x >= 0, x < C) --> (unsigned)x < CLuc Van Oostenryck3-2/+11
Such compares with a signed value are relatively common and can be easily be simplified into a single unsigned compare. So, do it. Note: This simplification triggers only 27 times in a x86-64 defconfig kernel. I expected more but I suppose it's because most checks aren't done against a constant or are done with unsigned values. Signed-off-by: Luc Van Oostenryck <luc.vanoostenryck@gmail.com>
2021-04-18add helper is_positive()Luc Van Oostenryck1-0/+5
Add a small helper to test if a pseudo is a positive (= non-negative) constant (for a given bitsize). It's meant to make some conditions more readable. Signed-off-by: Luc Van Oostenryck <luc.vanoostenryck@gmail.com>
2021-04-18add testcases for AND(x > 0, x <= C) --> x u<= CLuc Van Oostenryck2-0/+32
Signed-off-by: Luc Van Oostenryck <luc.vanoostenryck@gmail.com>
2021-04-18canonicalize constant signed compares toward zeroLuc Van Oostenryck2-6/+102
Currently, signed compares against a constant are canonicalized toward the smallest possible constant. So, the following canonicalization are done: x < 256 --> x <= 255 x < -2047 --> x <= -2048 This has two advantages: 1) it maximalizes the number of constants possible for a given bit size. 2) it allows to remove all < and all >= But it has also a serious disadvantages: a simple comparison against zero, like: x >= 0 is canonicalized into: x > -1 Which can be more costly for some architectures if translated as such , is also less readable than the version using 0 and is also sometimes quite more complicated to match in some simplification patterns. So, canonicalize it using 'towards 0' / using the smallest constant in absolute value. Signed-off-by: Luc Van Oostenryck <luc.vanoostenryck@gmail.com>
2021-04-18Merge branches 'fix-phisrc' and 'insert-last-insn' into memops-prepLuc Van Oostenryck14-200/+290
* fix and improve the check that protects try_to_simplify_bb() * fix remove_merging_phisrc() with duplicated CFG edges.
2021-04-18add testcases for simplification of casts.Luc Van Oostenryck4-24/+51
and remove one that didn't made much sense. Signed-off-by: Luc Van Oostenryck <luc.vanoostenryck@gmail.com>
2021-04-17memops: we can kill addresses unconditionallyLuc Van Oostenryck1-3/+1
In rewrite_load_instruction(), if the load instruction is converted into a phi-node, its address is then no more used and must be removed. However, this is only done when this address is not a symbol. This was explicitly done in the following commit because of the problem of removing an element from the usage list while walking this list: 602f6b6c0d41 ("Leave symbol pseudo usage intact when doing phi-node conversion.") But currently rewrite_load_instruction() is only used during memops simplification where the usage list is not walked. So, kill the address' usage unconditionally. Signed-off-by: Luc Van Oostenryck <luc.vanoostenryck@gmail.com>
2021-04-17memops: avoid using first_pseudo()Luc Van Oostenryck1-3/+5
The loop in rewrite_load_instruction() uses first_pseudo() to not have to special case the first element. But this slightly complicates further changes. So, simply use a null-or-no-null test inside the loop to identify this first element. Signed-off-by: Luc Van Oostenryck <luc.vanoostenryck@gmail.com>
2021-04-17memops: do not mess up with phisource's source identLuc Van Oostenryck1-1/+0
In rewrite_load_instruction(), when testing if all phi-sources are the same, the candidate is given an identifier if it hasn't one already. But doing this inside this loop is strange: * the pseudo may, at the end, not be selected but is changed anyway * the identifier should be given either when the phi-source is created or at the end of the loop if selected. So, do not change the identifier inside the selection loop. Signed-off-by: Luc Van Oostenryck <luc.vanoostenryck@gmail.com>
2021-04-17memops: remove obsolete commentLuc Van Oostenryck1-4/+0
The comment above rewrite_load_instruction(), about comparing phi-lists for equality, was (most probably) written when there was some intention to do CSE on phi-nodes or phi-sources. However, such CSE is currently not an objective at all. So, remove this comment. Signed-off-by: Luc Van Oostenryck <luc.vanoostenryck@gmail.com>
2021-04-17memops: find_dominating_parents()'s generation is redundantLuc Van Oostenryck1-8/+6
find_dominating_parents() has an argument 'generation' used to check if a BB has already been visited. But this argument is not needed since this generation is also stored in the field ::generation of the current BB. So, remove this argument. Signed-off-by: Luc Van Oostenryck <luc.vanoostenryck@gmail.com>
2021-04-17memops: dominates()'s first arg is redundantLuc Van Oostenryck3-12/+12
The first argument of dominates(), 'pseudo', is simply the 'src' pseudo of it's second argument, the load or store instruction. It's thus not needed to give it in a separate argument. So, remove this redundant argument, since it makes things slightly clearer. Signed-off-by: Luc Van Oostenryck <luc.vanoostenryck@gmail.com>
2021-04-17Merge branch 'deadstore'Luc Van Oostenryck4-11/+94
* memops: kill more dead stores
2021-04-17Merge branch 'linear'Luc Van Oostenryck1-1/+2
* linear: only allocate call instructions when needed
2021-04-17Merge branch 'untyped'Luc Van Oostenryck1-0/+11
* TODO: add some notes about pseudos being typeless
2021-04-17TODO: add some notes about pseudos being typelessLuc Van Oostenryck1-0/+11
Pseudos are untyped. It's usually OK because their type can nevertheless be retrieved in a simple way. But it also complicates things and worse in some cases the type is completely lost. Tell a bit more about it in the TODO file. Signed-off-by: Luc Van Oostenryck <luc.vanoostenryck@gmail.com>
2021-04-17Merge branch 'schecker'Luc Van Oostenryck9-18/+499
* add a symbolic checker
2021-04-17scheck: predefine __SYMBOLIC_CHECKER__Luc Van Oostenryck1-0/+1
It can be useful to use the same testcase for the symbolic checker and normal sparse (or test-linearize) processing. So, there must be a mean to somehow ignore the assertions used for the symbolic checker when it's not used (since these are otherwise not known to sparse). Resolve this by adding a predefine, __SYMBOLIC_CHECKER__, to the symbolic checker. Signed-off-by: Luc Van Oostenryck <luc.vanoostenryck@gmail.com>
2021-04-13scheck: support pre-conditions via __assume()Luc Van Oostenryck3-9/+31
A lot of simplifications are only valid when their variables satisfy to some conditions (like "is within a given range" or "is a power of two"). So, allow to add such pre-conditions via new _assume() statements. Internally, all such preconditions are ANDed together and what is checked is they imply the assertions: AND(pre-condition) implies assertion 1 ... Note: IIUC, it seems that boolector has a native mechanism for such things but I'm not sure if t can be used here. Signed-off-by: Luc Van Oostenryck <luc.vanoostenryck@gmail.com>
2021-04-13scheck: assert_const()Luc Van Oostenryck3-0/+21
Since, the symbolic checker check expressions at the ... symbolic level, this can be used to check if two expressions are equivalent but not if this equivalence is effectively used. So, add a new assertion (this time not at the symbolic level) to check if an expression which is expected to simplify to a constant is effectively simplified to this constant. Signed-off-by: Luc Van Oostenryck <luc.vanoostenryck@gmail.com>
2021-04-13scheck: allow multiple assertionsLuc Van Oostenryck2-6/+3
With the SMT solver used here, by default, once an expression is checked it's kinda consumed by the process and can't be reused anymore for another check. So, enable the incremental mode: it allows to call boolecter_sat() several times. Note: Another would be, of course, to just AND together all assertions and just check this but then we would lost the finer grained diagnostic in case of failure. Signed-off-by: Luc Van Oostenryck <luc.vanoostenryck@gmail.com>
2021-04-13scheck: assert_eq()Luc Van Oostenryck3-0/+17
Testing the equivalence of two sub-expressions can be done with with a single assertion like __assert(A == B). However, in some cases, Sparse can use the equality to simplify the whole expression although it's unable to simplify one of the two sub-expressions into the other. So, add a new assertion, __assert_eq(), testing the equality of the two expressions given in argument independently of each other. Signed-off-by: Luc Van Oostenryck <luc.vanoostenryck@gmail.com>
2021-04-13scheck: add a symbolic checkerLuc Van Oostenryck7-0/+356
Some instruction simplifications can be quite tricky and thus easy to get wrong. Often, they also are hard to test (for example, you can test it with a few input values but of course not all combinations). I'm used to validate some of these with an independent tool (Alive cfr. [1], [2]) which is quite neat but has some issues: 1) This tool doesn't work with Sparse's IR or C source but it needs to have the tests written in its own language (very close to LLVM's IR). So it can be used to test if the logic of a simplification but not if implemented correctly. 2) This tool isn't maintained anymore (has some bugs too) and it's successor (Alive2 [3]) is not quite as handy to me (I miss the pre-conditions a lot). So, this patch implement the same idea but fully integrated with Sparse. This mean that you can write a test in C, let Sparse process and simplify it and then directly validate it and not only for a few values but symbolically, for all possible values. Note: Of course, this is not totally stand-alone and depends on an external library for the solver (Boolector, see [4], [5]). Note: Currently, it's just a proof of concept and, except the included tests, it's only very slightly tested (and untested with anything more complex than a few instructions). [1] https://blog.regehr.org/archives/1170 [2] https://www.cs.utah.edu/~regehr/papers/pldi15.pdf [3] https://blog.regehr.org/archives/1722 [4] https://boolector.github.io/ [5] https://boolector.github.io/papers/BrummayerBiere-TACAS09.pdf Signed-off-by: Luc Van Oostenryck <luc.vanoostenryck@gmail.com>
2021-04-13.gitignore is a bit too greedyLuc Van Oostenryck1-17/+17
The current .gitignore specifies that the generated programs must be ignored. Good. However, this is done by just specifying the name of the program which has the effect of having any files or directories with the same name to be ignored too. This is not intended. Fix this using the pattern '/<name>' instead so that they match in the root folder. Signed-off-by: Luc Van Oostenryck <luc.vanoostenryck@gmail.com>
2021-04-13builtin: define a symbol_op for a generic op acting on integerLuc Van Oostenryck2-0/+65
This can be used to define some generic (polymorphic) builtin with a signature like: <name>(int) <name>(T, T) <name>(int, T) <name>(int, T, long, T, ... T) where T is some integer type which will be instantiated at each call. Signed-off-by: Luc Van Oostenryck <luc.vanoostenryck@gmail.com>
2021-04-10linear: only allocate call instructions when neededLuc Van Oostenryck1-1/+2
When linearizing a call expression, the corresponding instruction is allocated very early: - before the valdity are done - before the linearization is handled to one of the specific methods In both case it means that the allocated instruction is not used. Fix this by doing the allocation only once it's needed. Signed-off-by: Luc Van Oostenryck <luc.vanoostenryck@gmail.com>
2021-04-10export declare_builtins()Luc Van Oostenryck2-1/+3
Make declare_builtins() extern so that it can be used from other files. Signed-off-by: Luc Van Oostenryck <luc.vanoostenryck@gmail.com>
2021-04-04fix null-pointer crash with with ident same as one of the attributesLuc Van Oostenryck2-1/+13
match_attribute() will crash when the token has the same identifier as one of the attributes but is not an attribute. In this case, the corresponding symbol_op will be null but this is not checked. This seems to happen only with old-style declarations. Fix this by adding the missing null-check. Signed-off-by: Luc Van Oostenryck <luc.vanoostenryck@gmail.com>
2021-04-02fix remove_merging_phisrc()Luc Van Oostenryck2-11/+20
The current implementation of remove_merging_phisrc() can't work correctly when these phi-sources belong to a basic block with several children to the same target basic block (this happens commonly with OP_SWITCH). Fix this by directly scanning the source basic block for the presence of any phi-source. Once identified, the processing is kept unchanged: remove these phi-sources if a sibling phi-source will 'overwrite' them in the target block. Fixes: 2fdaca9e7175e62f08d259f5cb3ec7c9725bba68 Signed-off-by: Luc Van Oostenryck <luc.vanoostenryck@gmail.com>
2021-03-30Merge branch 'testsuite-extra' (early part)Luc Van Oostenryck1-0/+11
* testsuite: add option '-r' to 'test-suite format'
2021-03-28better check validity of phi-sourcesLuc Van Oostenryck1-8/+13
Transformations made by try_to_simplify_bb() are invalid if there isn't a one-to-one correspondence between the BB's parents and the phi-sources of the phi-node(s) in the BB. This correspondence is currently checked by checking if the number of phi-sources and the number of parent are equal, but this is only an approximation. Change this check into an exact one, using the fact that BBs in the parent list and phi-sources in the phi_list are in the same order. Signed-off-by: Luc Van Oostenryck <luc.vanoostenryck@gmail.com>
2021-03-28correctly count phi argumentsLuc Van Oostenryck2-1/+44
In a phi-node,pseudo_list_size() can't be used for counting its arguments because VOIDs must be ignored. Signed-off-by: Luc Van Oostenryck <luc.vanoostenryck@gmail.com>
2021-03-26additional testcase for remove_merging_phisrc()Luc Van Oostenryck1-0/+24
Signed-off-by: Luc Van Oostenryck <luc.vanoostenryck@gmail.com>
2021-03-25kill redundant stores (local)Luc Van Oostenryck2-1/+5
A store is called 'redundant' when the corresponding location already contains the value that will be stored. This patch removes such stores in the case where the memops which make them redundant is in the same basic block. Signed-off-by: Luc Van Oostenryck <luc.vanoostenryck@gmail.com>
2021-03-25kill parent's dead stores tooLuc Van Oostenryck3-2/+16
kill_dominated_stores() identify and remove dead stores (stores unneeded because the same location is overwritten later by another store) only when both stores are in the same basic block. Slightly improve this by also handling the case when the dead store is in a parent BB of the "live" store. Signed-off-by: Luc Van Oostenryck <luc.vanoostenryck@gmail.com>
2021-03-25volatile stores are never deadLuc Van Oostenryck1-0/+2
so they shouldn't be killed. Signed-off-by: Luc Van Oostenryck <luc.vanoostenryck@gmail.com>
2021-03-24extract try_to_kill_store() from kill_dominated_stores()Luc Van Oostenryck1-11/+19
Move the test/replace part of the store simplification in a separate function so that it can be reused. Signed-off-by: Luc Van Oostenryck <luc.vanoostenryck@gmail.com>
2021-03-24add testcases for stores simplificationsLuc Van Oostenryck3-0/+55
Signed-off-by: Luc Van Oostenryck <luc.vanoostenryck@gmail.com>
2021-03-21let ssa_rename_phi() use insert_last_instruction()Luc Van Oostenryck1-3/+3
Signed-off-by: Luc Van Oostenryck <luc.vanoostenryck@gmail.com>
2021-03-21let find_dominating_parents() use insert_last_instruction()Luc Van Oostenryck1-5/+5
Signed-off-by: Luc Van Oostenryck <luc.vanoostenryck@gmail.com>
2021-03-21let insert_phis() use insert_last_instruction()Luc Van Oostenryck1-4/+3
Signed-off-by: Luc Van Oostenryck <luc.vanoostenryck@gmail.com>
2021-03-21let insert_select() use insert_last_instruction()Luc Van Oostenryck1-6/+1
Signed-off-by: Luc Van Oostenryck <luc.vanoostenryck@gmail.com>
2021-03-21replace add_instruction_to_end() by insert_last_instruction()Luc Van Oostenryck1-9/+1
add_instruction_to_end() and insert_last_instruction() do exactly the same thing but with the arguments in the opposite order. So, replace add_instruction_to_end() by insert_last_instruction(). Signed-off-by: Luc Van Oostenryck <luc.vanoostenryck@gmail.com>
2021-03-21add insert_last_instruction()Luc Van Oostenryck1-0/+8
It's relatively common to have to add an instruction at the end of a BB. More exactly, at the end but just before the terminator instruction. What is done for this is: 1) remove the terminator 2) add the new instruction 3) add the terminator back This is a bit tedious, need to declare a temporary variable for the terminator and, more generally, it's low-level details. So, add an helper for doing this: insert_last_instruction(). Signed-off-by: Luc Van Oostenryck <luc.vanoostenryck@gmail.com>
2021-03-21testsuite: add option '-r' to 'test-suite format'Luc Van Oostenryck1-0/+11
Because laziness is a virtue, add an option '-r' to the 'format' subcommand of the testsuite to quickly create a test template for linearized code which should just return 1. Signed-off-by: Luc Van Oostenryck <luc.vanoostenryck@gmail.com>
2021-03-19fix phisources during SWITCH-BR conversionLuc Van Oostenryck2-1/+20
Like for CBR-BR conversion, when a target BB containing one or several phi-nodes is removed from an OP_SWITCH, the corresponding phi-source must be removed from the phi-node. However this is not done yet. Changing this by adding some code to convert_to_jump() to remove all phi-sources from the discarded targets if the converted instruction is an OP_SWITCH. Signed-off-by: Luc Van Oostenryck <luc.vanoostenryck@gmail.com>
2021-03-19use convert_to_jump() when converting a CBR with same targetsLuc Van Oostenryck2-12/+2
If a conditional branch has identical targets, it should be converted to a simple jump. This is done but using its own code. Change this by using the existing convert_to_jump() instead. This also allows any redundant phi-sources to be removed. Signed-off-by: Luc Van Oostenryck <luc.vanoostenryck@gmail.com>
2021-03-19fix phisources during CBR-BR conversionLuc Van Oostenryck3-2/+5
When a parent is removed from a BB containing one or several phi-nodes, the corresponding phi-sources must be removed from the phi-node. However this is not done and consequentially: * it becomes impossibly to correctly reason about the flow of values through these phi-nodes. * simplifications are missed (e.g. if-conversion). Signed-off-by: Luc Van Oostenryck <luc.vanoostenryck@gmail.com>
2021-03-19add remove_phisources()Luc Van Oostenryck2-0/+45
When a parent is removed from a BB containing one or several phi-nodes, the corresponding phi-sources become irrelevant and need to be removed from the phi-nodes. Add an helper for doing this: remove_phisources(). Signed-off-by: Luc Van Oostenryck <luc.vanoostenryck@gmail.com>
2021-03-19rename insert_branch() to convert_to_jump()Luc Van Oostenryck3-7/+7
Since the existing branch is now reused, nothing is inserted anymore. So, rename this function to the more explanatory: convert_to_jump(). Signed-off-by: Luc Van Oostenryck <luc.vanoostenryck@gmail.com>
2021-03-19let insert_branch() return a statusLuc Van Oostenryck3-17/+13
insert_branch() modifies the CFG and the usage of pseudos so these changes must be, in a way or another, notify to the upper layers. Currently this is done by setting 'repeat_phase' in the function itself. Let this function to also report the changes via its return value since this is usually useful for the caller to know and tend to leaner code too. Signed-off-by: Luc Van Oostenryck <luc.vanoostenryck@gmail.com>
2021-03-19move insert_branch() to flow.cLuc Van Oostenryck4-27/+27
Now that insert_branch() doesn't need to allocate a new instruction, there is no more reasons to have it defined in linearize.c So move it to flow.c which is more concerned with CFG changes. Signed-off-by: Luc Van Oostenryck <luc.vanoostenryck@gmail.com>
2021-03-19let insert_branch() reuse the terminating instructionLuc Van Oostenryck1-10/+6
insert_branch() changes a switch or a conditional branch into a jump. This is implemented by deleting the old instruction and allocating the new one. This is not needed here since no reference to the old instruction is kept. So, simply reuse the terminating instruction and change it. Signed-off-by: Luc Van Oostenryck <luc.vanoostenryck@gmail.com>
2021-03-19fold remove_parent() into insert_branch()Luc Van Oostenryck1-6/+1
Fold remove_parent() into its only user, insert_branch(), since it's now just a wrapper around remove_bb_from_list(). Signed-off-by: Luc Van Oostenryck <luc.vanoostenryck@gmail.com>
2021-03-19simplify remove_parent()Luc Van Oostenryck1-2/+0
remove_parent() is a simple wrapper around remove_bb_from_list() which also set REPEAT_CFG_CLEANUP if the list becomes empty. But its only user, insert_branch(), doesn't need REPEAT_CFG_CLEANUP to be set. So, simplify this wrapper by keeping only the call to remove_bb_from_list().
2021-03-19remove insert_branch() redundant argLuc Van Oostenryck4-7/+8
insert_branch()'s first argument must be the BB of the instruction given in the second argument. So, remove it from the argument and simply use insn->bb instead. Signed-off-by: Luc Van Oostenryck <luc.vanoostenryck@gmail.com>
2021-03-19add testcases to check if phi-sources from removed targets are removed tooLuc Van Oostenryck4-0/+78
Signed-off-by: Luc Van Oostenryck <luc.vanoostenryck@gmail.com>
2021-03-19Revert "simplify CBR-CBR on the same condition"Luc Van Oostenryck1-106/+0
The commit 7cd2ce022575 ("simplify CBR-CBR on the same condition") added a generalization of the existing CBR-CBR simplification using the dominance tree. The problem is that as soon as a change is made to the CFG, the dominance tree become invalid and should be rebuilt (which is costly to do for each CFG changes) or updated (which is quite complex). So, for now, revert this commit. Reverts: 7cd2ce022575fbd383bb39b54f1e0fa402919da2. Signed-off-by: Luc Van Oostenryck <luc.vanoostenryck@gmail.com>
2021-03-13canonicalize ((x & M) == M) --> ((x & M) != 0) when M is a power-of-2Luc Van Oostenryck2-0/+16
and same for its dual: ((x & M) != M) --> ((x & M) == 0) Beside the canonicalization itself, these simplifications are useful because the compare against 0 can often be further simplified (for example when it is used by OP_CBR or OP_SELECT). Signed-off-by: Luc Van Oostenryck <luc.vanoostenryck@gmail.com>
2021-03-12Merge branches 'fix-ssa' and 'cmp-and-or' into nextLuc Van Oostenryck9-4/+211
* fix SSA conversion of mismatched memops * simplify CMP(AND(x,M), C) and CMP(OR(x,M), C)
2021-03-10no needs to use MARK_CURRENT_DELETED() for multi-jumpsLuc Van Oostenryck1-1/+1
MARK_CURRENT_DELETED() was added for the case(s) where an element must be removed from the list but the address of the other elements must not be changed. In this case of effectively removing the element from it list, the element is 'marked' as deleted in the list and the list walking macros will later take this in account. However, this is never needed for multi-jumps. So, use the usual DELETE_CURRENT_PTR() for them. Signed-off-by: Luc Van Oostenryck <luc.vanoostenryck@gmail.com>
2021-03-10simplify (x | M) cmpu CLuc Van Oostenryck2-1/+16
Signed-off-by: Luc Van Oostenryck <luc.vanoostenryck@gmail.com>
2021-03-10simplify (x | M) cmps CLuc Van Oostenryck2-1/+14
Signed-off-by: Luc Van Oostenryck <luc.vanoostenryck@gmail.com>
2021-03-10simplify (x | M) {==,!=} CLuc Van Oostenryck2-1/+15
Signed-off-by: Luc Van Oostenryck <luc.vanoostenryck@gmail.com>
2021-03-10simplify (x & M) {==,!=} CLuc Van Oostenryck2-1/+8
Signed-off-by: Luc Van Oostenryck <luc.vanoostenryck@gmail.com>
2021-03-10simplify (x & M) cmps 0Luc Van Oostenryck2-1/+4
Signed-off-by: Luc Van Oostenryck <luc.vanoostenryck@gmail.com>
2021-03-10simplify (x & M) cmpu CLuc Van Oostenryck2-1/+16
Signed-off-by: Luc Van Oostenryck <luc.vanoostenryck@gmail.com>
2021-03-10simplify (x & M) cmps CLuc Van Oostenryck2-1/+25
Signed-off-by: Luc Van Oostenryck <luc.vanoostenryck@gmail.com>
2021-03-10add testcases for constant compares against AND/ORLuc Van Oostenryck7-0/+116
Signed-off-by: Luc Van Oostenryck <luc.vanoostenryck@gmail.com>
2021-03-10change testing of signed compares against SMIN or SMAXLuc Van Oostenryck1-4/+4
These tests are written by testing if the comparisons are equal to their expected value: 0 or 1. So, a compare of a compare but such compares of compare have their own simplification which defeats what's tested here. So, rewrite the test to avoid such compares of compare. Signed-off-by: Luc Van Oostenryck <luc.vanoostenryck@gmail.com>
2021-03-09ssa: remove single store optimizationLuc Van Oostenryck1-64/+0
It's not clear if this is an optimization or not. So, remove it. Signed-off-by: Luc Van Oostenryck <luc.vanoostenryck@gmail.com>
2021-03-09ssa: fix conversion with mismatched size or offsetLuc Van Oostenryck3-20/+80
The SSA conversion works under the assumption that all the memory operations on a given symbol always refer to the same object. So, exclude the conversion of variables where: * memory operations do not always match in size or offset * there is an implicit integer/float conversion. Signed-off-by: Luc Van Oostenryck <luc.vanoostenryck@gmail.com>
2021-03-09ssa: avoid SSA conversion of packed bitfieldsLuc Van Oostenryck2-1/+3
Packed bitfields are incompatible with the SSA conversion which works on the assumption that memory operations are done on the whole symbol. So, directly exclude packed bitfields from the SSA conversion. Signed-off-by: Luc Van Oostenryck <luc.vanoostenryck@gmail.com>
2021-03-09ssa: the sparse set is not neededLuc Van Oostenryck4-92/+4
The implementation of a 'sparse set without initialization' was somehow needed during the initial design but it's not needed anymore. So, remove the implementation and replace its use by the usual bb->generation mechanism. Signed-off-by: Luc Van Oostenryck <luc.vanoostenryck@gmail.com>
2021-03-09ssa: add some testcases for mismatched memopsLuc Van Oostenryck2-0/+85
The SSA conversion is incorrect when the size or offset of the memory operations doesn't match. It shouldn't be done at all. So, add a few testcases for this. Signed-off-by: Luc Van Oostenryck <luc.vanoostenryck@gmail.com>
2021-03-08Merge branch 'uniq-phinode'Luc Van Oostenryck9-65/+16
* phi-sources can only have a single user (or none)
2021-03-08Merge branch 'ptrlist-generic'Luc Van Oostenryck4-25/+26
* ptrlist: small API improvements These improvements will be used by various incoming series. Thanks to Ramsay Jones for finding a bunch of typos and suggesting some improved phrasing. -- Luc
2021-03-08phi-sources can only have a single user (or none)Luc Van Oostenryck9-65/+16
Currently, OP_PHISOURCES have a list as member, 'phi_users', that should link to all phi-nodes using them but: *) phi-sources are never shared between phi-nodes *) this list is useless because it's only created during liveness and not used after. So, replace the list by a simple pointer to hold the unique phi-node using it and keep this link updated during all its lifetime. Signed-off-by: Luc Van Oostenryck <luc.vanoostenryck@gmail.com> Acked-by: Linus Torvalds <torvalds@linux-foundation.org>
2021-03-08ptrlist: change return value of linearize_ptr_list()/ptr_list_to_array()Luc Van Oostenryck2-7/+7
The function linearize_ptr_list() is annoying to use because it returns the number of elements put in the array. So, if you need to know if the list contained the expected number of entries, you need to allocate an array with one extra entry and check that the return value is one less than this size. So, change the function to return the total number of entries in the list. In other words, the return value corresponds now to the number of entries that could be copied if the size would be unlimited, much like it's done for snprintf(). The number of entries effectively copied stays, of course, limited by the size specified for the array. Signed-off-by: Luc Van Oostenryck <luc.vanoostenryck@gmail.com>
2021-03-06ptrlist: make linearize_ptr_list() genericLuc Van Oostenryck2-2/+8
The ptrlist API has a function to copy the elements of a ptrlist into an array but it's not typed and thus needs a wrapper (or casts) for each type it's used for. Also, 'linearize' is confusing since this is unrelated to Sparse's linearization. Simplify this by adding a generic (but type-safe) macro for this with a more descriptive name: ptr_list_to_array() Signed-off-by: Luc Van Oostenryck <luc.vanoostenryck@gmail.com>
2021-03-06ptrlist: use ptr_list_nth() instead of linearize_ptr_list()Luc Van Oostenryck1-12/+1
Sparse has a few extra checkers for some functions. The one for memset has its own helper to retrieve its 3rd arguments. Remove this helper and use the generic ptr_list_nth() instead. Signed-off-by: Luc Van Oostenryck <luc.vanoostenryck@gmail.com>
2021-03-06ptrlist: add pop_ptr_list()Luc Van Oostenryck1-0/+6
Some algorithms need a stack or a working list from which the last element can be removed. The ptrlist API has a function to do this but it's not typed and thus needs a wrapper for each type it's used for. Simplify this by adding a generic (but type-safe) macro for this while also giving it a nicer name: pop_ptr_list(). Signed-off-by: Luc Van Oostenryck <luc.vanoostenryck@gmail.com>
2021-03-06ptrlist: change TYPEOF() into PTRLIST_TYPE()Luc Van Oostenryck1-5/+5
The name of the macro TYPEOF() is too generic and doesn't explain that it only returns the type of the pointers stored in ptrlists. So, change the name to something more explicit: PTRLIST_TYPE(). Signed-off-by: Luc Van Oostenryck <luc.vanoostenryck@gmail.com>
2021-03-06ptrlist: remove one pointer level from TYPEOF()Luc Van Oostenryck1-4/+4
The macro TYPEOF() return the type of the addresses of the pointers stored in the list. That's one level too much in general. Change it to simply return the type of the stored pointers. Signed-off-by: Luc Van Oostenryck <luc.vanoostenryck@gmail.com>
2021-03-05Merge branch 'slice'Luc Van Oostenryck7-16/+9
* slice: small reorg of OP_SLICE in preparation for some incoming changes
2021-03-04Merge branch 'path-norm'Luc Van Oostenryck1-0/+6
* pre-processing: strip leading "./" from include paths
2021-03-01Merge branch 'fix-restrict' into nextLuc Van Oostenryck2-1/+23
* fix the type in the assignment of 0 to a restricted variable
2021-03-01pre-proc: do some path normalizationLuc Van Oostenryck1-0/+6
An header file like 'header.h': #pragma once #include "./header.h" doesn't work because: 1) both filenames are different, so it will be be included anyway 2) after that it will be included again under the name "././header.h" and so on until it eventually fails with ENAMETOOLONG. Prevent this by stripping leading "./"s in the paths. This is not good enough for testing file equivalence by is enough to avoid the loop. Link: https://lore.kernel.org/r/CAHk-=wjFWZMVWTbvUMVxQqGKvGMC_BNrahCtTkpEjxoC0k-T=A@mail.gmail.com Signed-off-by: Luc Van Oostenryck <luc.vanoostenryck@gmail.com>
2021-02-28liveness: use 'src' for unops instead of 'src1'Luc Van Oostenryck1-1/+1
2021-02-28slice: display the source's size, like for unopsLuc Van Oostenryck1-1/+1
When displaying an OP_SLICE, the width is shown but the size of the source pseudo is useful too. So, display this size in a similar manner to the unops. Signed-off-by: Luc Van Oostenryck <luc.vanoostenryck@gmail.com>
2021-02-28slice: OP_SLICE needs the source's type: make it a kind of unopLuc Van Oostenryck3-10/+5
OP_SLICE's source's type is needed for some simplifications. For example, in some cases it can be simplified into OP_TRUNC. So, merge its representation with the one for unops which also need the source's type. Signed-off-by: Luc Van Oostenryck <luc.vanoostenryck@gmail.com>
2021-02-28slice: remove unneeded nr_nrbits from EXPR_SLICELuc Van Oostenryck3-3/+2
EXPR_SLICE::r_nrbits is necessarily equal to its type's bit size. So remove this redundancy. Signed-off-by: Luc Van Oostenryck <luc.vanoostenryck@gmail.com>
2021-02-28slice: remove unneeded len from OP_SLICELuc Van Oostenryck3-4/+3
OP_SLICE::len is necessarily equal to the result size. So remove this redundancy. Signed-off-by: Luc Van Oostenryck <luc.vanoostenryck@gmail.com>
2021-02-28asm-out0: fix a test failure on 32-bit systemsRamsay Jones1-1/+1
Signed-off-by: Ramsay Jones <ramsay@ramsayjones.plus.com> Signed-off-by: Luc Van Oostenryck <luc.vanoostenryck@gmail.com>
2021-02-28linearize.h: fix some 'selfcheck' warningsRamsay Jones1-2/+2
Commits 34c57a7f ("asm-mem: does it clobber memory?", 2021-02-20) and d6721b38 ("asm-mem: does it output to memory?", 2021-02-20) both add a single bit bitfield to the 'struct asm' part of the union contained within the 'struct instruction'. This causes the 'selfcheck' target to issue several 'dubious one-bit signed bitfield' errors. In order to suppress these errors, change the type of the bitfields to an unsigned type. Signed-off-by: Ramsay Jones <ramsay@ramsayjones.plus.com> Signed-off-by: Luc Van Oostenryck <luc.vanoostenryck@gmail.com>
2021-02-25Merge branch 'objsize'Luc Van Oostenryck5-1/+144
* expand __builtin_object_size()
2021-02-25Merge branch 'asm-dom'Luc Van Oostenryck5-24/+97
* asm: output *memory* operands need their address as *input* * asm: teach dominates() about OP_ASM
2021-02-25expand __builtin_object_size()Luc Van Oostenryck4-1/+140
__builtin_object_size() is one of these builtins that must be somehow expanded because it can't possibly be implemented at runtime. It's used by the kernel's copy_{to,from}_user() and the 'fortified' string functions, as well as by userspace's 'checked string/memory functions' like __builtin___memcpy_chk(). So, use the normal builtin expansion interface for this one too. This gets rid of 2/3 of them when used on the kernel and shaves ~0.5% of the total IR code (with x86's defconfig). Notes: 1) What is covered is an object symbol, with an optional designator of arbitrary complexity, ignoring casts and accessed via an optional chain of simple dereferences. Maybe some access path need to be added. 2) Anything with dynamic value is currently considered either as unknown (VLAs, variables or parameters) or left for a later stage (any function calls, including functions known to allocate memory given that attribute alloc_size() is not yet supported). 3) It's not totally clear to me when to give up (and thus return 'size unknown') and when things can or must be left to the simplification phase. This matters because __builtin_object_size() is relatively often used with __builtin_constant_p(). 4) Currently, only type 0 is really supported. Given the way designators are evaluated and expanded (information is lost because the expressions are overwritten), to support the other types, the expansion of __builtin_object_size() should be done during evaluation itself, much like it's done for sizeof() and offsetof(). Signed-off-by: Luc Van Oostenryck <luc.vanoostenryck@gmail.com>
2021-02-24fix eval of the assignment of a non-restricted value to a restricted variableLuc Van Oostenryck2-1/+23
Assignment to restricted variables are severely ... restricted. Nevertheless, one value is always fine because it has always the same bit representation: 0. So, 0 is accepted unconditionally but this creates a problem because the type of this 0 needs to be adjusted. Otherwise 0 (int) is assigned as-is even on restricted variable with a different bit-length. Fix this by casting the value to the target type before accepting it. Signed-off-by: Luc Van Oostenryck <luc.vanoostenryck@gmail.com>
2021-02-21asm-mem: teach dominates() about OP_ASMLuc Van Oostenryck2-1/+6
The function dominates() needs to know if an OP_ASM instruction may modify. Use the information now available in the instruction to return the answer. Signed-off-by: Luc Van Oostenryck <luc.vanoostenryck@gmail.com>
2021-02-21asm-mem: does it output to memory?Luc Van Oostenryck2-0/+2
If an asm statement have a memory output operand, it modifies memory. Since this information is needed during memops simplification, add this info directly in the corresponding instruction, avoiding the need to scan the output operands list each time. Signed-off-by: Luc Van Oostenryck <luc.vanoostenryck@gmail.com>
2021-02-21asm-mem: does it clobber memory?Luc Van Oostenryck2-1/+8
An asm statement can specify that it clobbers memory. Add this info directly in the corresponding instruction, avoiding the need to scan the clobber list each time. Signed-off-by: Luc Van Oostenryck <luc.vanoostenryck@gmail.com>
2021-02-21asm-mem: add testcase for missing reload after asm memopsLuc Van Oostenryck1-0/+15
Memory simplification is done with the help of the function dominates() which determine when memory instructions interfere. This function handles OP_CALLs, OP_LOADs and OP_STOREs but memory can also be changed via OP_ASMs. Add a testcase showing this. Signed-off-by: Luc Van Oostenryck <luc.vanoostenryck@gmail.com>
2021-02-21reorg dominates()Luc Van Oostenryck1-4/+7
To prepare the handling of OP_ASM instructions, reorganize the opcode tests to use a switch. Signed-off-by: Luc Van Oostenryck <luc.vanoostenryck@gmail.com>
2021-02-21asm: output *memory* operands need their address as *input*Luc Van Oostenryck2-9/+23
The addresses needed by memory output operands are linearized (and placed) after the ASM instruction needing them. So, split add_asm_output() in 2 parts: one generating only the addresses for memory operands and called before issuing the body, and another one doing the usual copy of (non-memory) output operands back into their corresponding variables. Signed-off-by: Luc Van Oostenryck <luc.vanoostenryck@gmail.com>
2021-02-21asm: factor out add_asm_rule() from add_asm_{in,out}put()Luc Van Oostenryck1-11/+12
The functions add_asm_input() and add_asm_output() are very similar. So, factorize out the common part. Signed-off-by: Luc Van Oostenryck <luc.vanoostenryck@gmail.com>
2021-02-21asm: add testcase for problem with output addressesLuc Van Oostenryck1-0/+26
The addresses needed by memory output operands are linearized (and placed) after the ASM instruction needing them. So, add a test case for this. Signed-off-by: Luc Van Oostenryck <luc.vanoostenryck@gmail.com>
2021-02-08ptrlist: make ptr_list_nth_entry() generic with ptr_list_nth()Luc Van Oostenryck1-0/+4
The library operation on pointer list necessarily act on the untyped version of the list. To use them with type checking, they must either be wrapped in inline function using the desired type or be used via some macro doing the type checking. Do this later solution for ptr_list_nth_entry(). Signed-off-by: Luc Van Oostenryck <luc.vanoostenryck@gmail.com>
2021-01-31Merge branch 'fix-join-cond'Luc Van Oostenryck2-2/+21
* fix add_join_conditional() when one of the alternative is VOID
2021-01-31fix add_join_conditional() when one of the alternative is VOIDLuc Van Oostenryck2-2/+21
add_join_conditional()'s job is to take the 2 alternatives of the conditional, make a phi-node from them and return the corresponding pseudo but if one of the alternatives is not available it's useless to create a phi-node and the other alternative can then directly be returned. The problem is that in this later case, the pseudo directly returned is the PSEUDO_PHI of the corresponding phi-source. This gives erroneous code like, for example: phisrc.32 %phi1 <- $0 ret.32 %phi1 instead of: ret.32 $0 since the %ph1 should only be used by a phi-node instruction. Fix this by returning phi-source's operand instead. Signed-off-by: Luc Van Oostenryck <luc.vanoostenryck@gmail.com>
2021-01-28Merge branch 'optim-cmps'Luc Van Oostenryck8-19/+200
* simplify and canonicalize signed compares
2021-01-27Makefile: fix version.h dependenciesKyle Russell6-6/+9
This guarantees the generated version.h will exist before attempting to compile any c files that include it. Several source files include the generated version.h, but not all declare a proper make dependency. $ grep -r 'version\.h' *.c compile-i386.c:#include "version.h" lib.c:#include "version.h" options.c:#include "version.h" This allows a sufficiently parallelized make invocation to encounter ENOENT. CC compile-i386.o compile-i386.c:60:21: fatal error: version.h: No such file or directory compilation terminated. Makefile:253: recipe for target 'compile-i386.o' failed make: *** [compile-i386.o] Error 1 Signed-off-by: Kyle Russell <bkylerussell@gmail.com> [luc.vanoostenryck@gmail.com: modified so that only version.c depends on version.h] Signed-off-by: Luc Van Oostenryck <luc.vanoostenryck@gmail.com>
2021-01-26cmps: canonicalize SEL(x > 0, a, -a) --> SEL(x >= 0, a, -a)Luc Van Oostenryck2-1/+14
When computing the absolute value using an expression like: (a > 0) ? a : -a it's irrelevant to use '>' or '>=', both will give the same result since 0 is its own negation. Canonicalize these equivalent expressions, such that OP_GE is always used. Signed-off-by: Luc Van Oostenryck <luc.vanoostenryck@gmail.com>
2021-01-26cmps: canonicalize SEL(x {<,<=} y, a, b) --> SEL(x {>=,>} y, b, a)Luc Van Oostenryck2-1/+7
Both compares and OP_SELECT are anti-symmetrical: swapping the arguments is equivalent to inversing the condition. As consequence, when combined, they're symmetrical: swapping the arguments of the compare (or equivalently reversing the direction of the compare) and swapping the operand of the OP_SELECT is a no-op, both forms are equivalent. So, canonicalize these to always use OP_GT or OP_GE. Signed-off-by: Luc Van Oostenryck <luc.vanoostenryck@gmail.com>
2021-01-26cmps: canonicalize signed compares with constantLuc Van Oostenryck2-1/+2
Modify the constants to canonicalize (x < C) to (x <= (C-1)) and (x <= C) to (x > (C-1)). This choice is partially arbitrary but 1) it's the one with the smallest positive constants, 2) it eliminates all OP_SET_LT & OP_SET_GE with a constant. A disadvantage of this choice is that we lost some compares with 0: (x < 0) is now canonicalized into (x <= -1). Note: Another good choice would be to canonicalize using the smallest absolute constants. This would keep compares with 0 but would also keep the 4 kinds of comparison. Signed-off-by: Luc Van Oostenryck <luc.vanoostenryck@gmail.com>
2021-01-26cmps: canonicalize SMIN/SMAX +- 1 --> EQ/NELuc Van Oostenryck2-1/+8
Compares with SMIN + 1 or SMAX - 1 are equivalent to an equality testing. For example, (x < SMIN + 1) is the same as (x == SMIN). Canonicalize these to the equality testing since these are usually simpler to handle. Signed-off-by: Luc Van Oostenryck <luc.vanoostenryck@gmail.com>
2021-01-26cmps: canonicalize signed compares with SMIN/SMAXLuc Van Oostenryck2-1/+8
The remaining compares with SMIN or SMAX are equivalent to an equality testing. For example, (x < SMAX) is the same as (x != SMAX). Canonicalize these to the equality testing since these are usually simpler to handle. Signed-off-by: Luc Van Oostenryck <luc.vanoostenryck@gmail.com>
2021-01-26cmps: simplify signed compares with SMIN or SMAXLuc Van Oostenryck2-1/+17
Simplify away signed compares with SMIN or SMAX which can be statically be determined to be always true or always false. Signed-off-by: Luc Van Oostenryck <luc.vanoostenryck@gmail.com>
2021-01-26cmps: add testcases for simplification of signed comparesLuc Van Oostenryck6-0/+106
Signed compares miss some simplifications/canonicalizations. Add some testcases for them. Signed-off-by: Luc Van Oostenryck <luc.vanoostenryck@gmail.com>
2021-01-26cmpu: fix canonicalization of unsigned (x {<,>=} C) --> (x {<=,>} C-1)Luc Van Oostenryck1-2/+2
In Sparse, the PSEUDO_VALUEs are required to be truncated at their effective size. For example, for a 32-bit instruction and Sparse using 64-bit integers, a pseudo of -1 must contain the value 0x00000000ffffffff, not 0xffffffffffffffff. Add the missing truncation in the canonicalization here. Fixes: c355e5ac5dce35f3d95c30cd5e2e9a5074c38437 Signed-off-by: Luc Van Oostenryck <luc.vanoostenryck@gmail.com>
2021-01-26cmps: fix simplification of sext(x) + signed compare of {SMAX,SMIN}Luc Van Oostenryck2-13/+37
Commit a1c1b9236d5d ("cmp: simplify sext(x) cmps {SMAX,SMIN}") had a double error (wrong size and wrong compare direction) which was hidden because of too narrow testcases. So, fix the simplification and extend the testcases. Fixes: a1c1b9236d5d4af1681a45ced26f8350bd7721c2 Signed-off-by: Luc Van Oostenryck <luc.vanoostenryck@gmail.com>
2021-01-26cmps: make clearer we're using the operands' sizeLuc Van Oostenryck1-4/+5
When handling compares of an {zero,sign}-extended value, the size of these extended values are used but this size is just the operands' size of the compares. Make this clearer by using a single variable 'size' for it. Signed-off-by: Luc Van Oostenryck <luc.vanoostenryck@gmail.com>
2021-01-25Merge branches 'fix-can-move-to' and 'asr-synth' into nextLuc Van Oostenryck2-1/+39
2021-01-24simplify LSR + SEXT into ASRLuc Van Oostenryck2-1/+39
A logical shift right followed by a sign extension is equivalent to an arithmetic shift. Teach this to sparse. Signed-off-by: Luc Van Oostenryck <luc.vanoostenryck@gmail.com>
2021-01-24fix possible circular definition with can_move_to()Luc Van Oostenryck1-0/+2
can_move_to() is used to test if it is safe for a given pseudo to be used by some instruction. This is done by checking that the pseudo is defined 'before' the instruction. This should, of course, reject the cases where the pseudo is defined by the instruction itself because it would create a circular definition. However, this special case was not checked. Fix this by adding the missing check. Signed-off-by: Luc Van Oostenryck <luc.vanoostenryck@gmail.com>
2021-01-23Merge branch 'unnamed-qual'Luc Van Oostenryck1-0/+28
* handle qualified anonymous structures
2021-01-23Merge branch 'fix-sext-cmps'Luc Van Oostenryck1-0/+2
2021-01-22handle qualified anonymous structuresLuc Van Oostenryck1-0/+28
The kernel is trying to use a unnamed struct to mark a group of fields as being 'const' and get a warning if one of its member is assigned. GCC gives indeed a warning but Sparse and clang don't. So, the type qualifiers of the anonymous struct need to be propagate to the members. An easy, one-liner, solution is to handle this inside find_identifier(), where access to the members are recursively searched inside sub-structures. It's very easy but it feels wrong to do semantics inside this function. Worse, it's only working for members that are effectively accessed, doing a type evaluation on the anonymous struct (or its parent) would, by itself, not handle this. So, the solution chosen here is to handle this during type examination, more precisely, inside examine_struct_union_type(), where things are a bit more complicated (it can't be done when examining the members themselves because only the parent SYM_STRUCT is accessible and the qualifiers are in the SYM_NODE, so it needs to be done when examining the anonymous struct itself) but can be done for all members. Note: It would seem logical to also handle at least all qualifier-like attributes but GCC seems to only bother with the true qualifiers and ignore things like attributes and alignment specifiers. Link: lore.kernel.org/r/CAHk-=wj4Kviw8q2Sx9vrrvyn3uWK-zNi4uGRx=5bzde0Cio8uQ@mail.gmail.com Link: lore.kernel.org/r/CAHk-=wjdJmL22+zk3_rWAfEJJCf=oDxiJ530qk-WNk_Ji0qhxw@mail.gmail.com Thanks-to: Linus Torvalds <torvalds@linux-foundation.org> Signed-off-by: Luc Van Oostenryck <luc.vanoostenryck@gmail.com>
2021-01-17fix type of canonicalization of sext + unsigned compareLuc Van Oostenryck1-0/+2
In commit 4a5f616407e2 ("cmp: canonicalize sext(x) cmpu C (with C >= SMAX)"), the operand is replaced to avoid a sign extension but the corresponding type was not updated. Fix this now. Fixes: 4a5f616407e26efb67013f8267adef2d6e093bf1 Signed-off-by: Luc Van Oostenryck <luc.vanoostenryck@gmail.com>
2021-01-02removed an unused parameter for show_symbol_list()Bernd Petrovitsch3-4/+4
A trivial patch to remove an unused parameter. Link: https://lore.kernel.org/linux-sparse/1282818698.12802.23.camel@thorin Signed-off-by: Luc Van Oostenryck <luc.vanoostenryck@gmail.com>
2021-01-02shut up a silly -Wmaybe-uninitialized warningLuc Van Oostenryck1-1/+1
I understand why the compiler would complain about this 'maybe-uninitialized' variable (it's always initialized when used) but I don't understand why the warning suddenly occurs while the variable have already been dereferenced several times; But well ... Initialize it with NULL to shut up the warning. Signed-off-by: Luc Van Oostenryck <luc.vanoostenryck@gmail.com>
2021-01-01Merge branch 'packed'Luc Van Oostenryck20-45/+447
* packed: add support for __packed struct
2020-12-31Merge branches 'fix-rem-usage', 'ptrlist-no-mix' and 'diet-bb' into nextLuc Van Oostenryck3-19/+23
* fix rem_usage() when the pseudo has a use list but is not PSEUDO_REG * ptrlist: avoid mixing reverse and non-reverse macros * shrink struct basic_block
2020-12-29fix rem_usage()Luc Van Oostenryck1-1/+1
rem_usage() is used to remove an element from a def-use chain. Optionally, if the chain become empty, the defining instruction can also be killed. This optional part is currently be done on all pseudos but only those having a definition should be concerned. Fix this by adding a check so that only PSEUDO_REGs and PSEUDO_PHIs are killed. Signed-off-by: Luc Van Oostenryck <luc.vanoostenryck@gmail.com>
2020-12-29add helper has_definition()Luc Van Oostenryck1-0/+5
Add the helper has_definition() to check if the pseudo belong to one of the pseudo types having a definition: PSEUDO_REG & PSEUDO_PHI. Signed-off-by: Luc Van Oostenryck <luc.vanoostenryck@gmail.com>
2020-12-29packed: add support for __packed structLuc Van Oostenryck10-13/+14
Now that the 'packed' attribute is parsed and propagated into the type system, adapt the layout of structures. Signed-off-by: Luc Van Oostenryck <luc.vanoostenryck@gmail.com>
2020-12-29packed: no out-of-bound access of packed bitfieldsLuc Van Oostenryck2-2/+12
There is (at least) 2 ways by which packed bitfields doesn't follow normal layout/access rules and as consequence can't (always) be accessed the usual way (load the whole underlying word, then shift and mask to isolate the bitfield). At least two different cases are a concern: 1) there is no padding at the end of a bitfield sequence. For example, the following struct is only 3 bytes width: struct s { int f:24; } __packed; So, trying to access the bitfield by first doing a 32-bit load will create an out-of-bound access. 2) a bitfield smaller than one word may need more than one word to be accessed. For example, with the following struct struct { int a:5; int f:30; int z:5; } __packed; the bitfield 'f', while smaller than one 32-bit word, can't be accessed with a single 32-bit access. At machine level, these bitfields should be accessed with several, possibly smaller, loads and their corresponding values reconstructed from these, making things much more complicated than for non-packed bitfields. But at IR level, things can be a little more flexible and things can stay simple by using sub-word or super-word accesses (until these need to be lowered to be usable at machine level). In other words, the example here can be safely accessed with respectively a 24-bit and a 40-bit load. This is what is done in this patch. Signed-off-by: Luc Van Oostenryck <luc.vanoostenryck@gmail.com>
2020-12-29struct-attr: fix: do not ignore struct/union/enum type attributesLuc Van Oostenryck6-5/+2
GCC's syntax for type attributes is specified as: An attribute specifier list may appear as part of a struct, union or enum specifier. It may go either immediately after the struct, union or enum keyword, or after the closing brace. The former syntax is preferred. Where attribute specifiers follow the closing brace, they are considered to relate to the structure, union or enumerated type defined, not to any enclosing declaration the type specifier appears in, and the type defined is not complete until after the attribute specifiers. In the section about type attributes, it's also said: You may specify type attributes in an enum, struct or union type declaration or definition by placing them immediately after the struct, union or enum keyword. A less preferred syntax is to place them just past the closing curly brace of the definition. So, while placing the attribute after the closing curly is not preferred, it is cleary legal (and it seems to be much more popular than placing them just after the struct, union or enum keyword). However, currently sparse doesn't handle this correctly: - these attributes are parsed in declaration_specifiers() and added to the current decl_state - when the ';' ending the type declaration is reached, the plain struct/union/enum is used and the content of the decl_state is simply ignored. - if the declaration is for a variable, then those attributes are assigned to the variable (but not to the type). Fix this by calling handle_attribute() once we have reached the closing '}' of a struct/union/enum definition and applying these attributes, if any, directly to the current base type. Signed-off-by: Luc Van Oostenryck <luc.vanoostenryck@gmail.com>
2020-12-29struct-attr: fix type attribute like 'struct __attr { ... }'Luc Van Oostenryck1-1/+3
In a declaration like: struct <some attribute> { ... } the attribute belong to the type but is currently handled as belonging to the whole declaration. Fix this by handling such attributes in a local 'decl_state' and applying them once the closing '}' is reached. Signed-off-by: Luc Van Oostenryck <luc.vanoostenryck@gmail.com>
2020-12-29struct-attr: prepare to handle attributes at the end of struct definitions (3)Luc Van Oostenryck1-9/+6
Type attributes for struct can be placed either just after the keyword 'struct' or after the '}' ending its definition but this later case is currently ignored. Prepare the handling of this by having the 3 following cases in sequence: 1) a tag is present 2) no tag present but is followed by an opening brace 3) neither of these, so it's an error. Signed-off-by: Luc Van Oostenryck <luc.vanoostenryck@gmail.com>
2020-12-29struct-attr: prepare to handle attributes at the end of struct definitions (2)Luc Van Oostenryck1-13/+13
Type attributes for struct can be placed either just after the keyword 'struct' or after the '}' ending its definition but this later case is currently ignored. Prepare the handling of this by restructuring the code handling struct specifiers, namely inverting the condition so that the function can return early to make next patch's job easier. Signed-off-by: Luc Van Oostenryck <luc.vanoostenryck@gmail.com>
2020-12-29struct-attr: prepare to handle attributes at the end of struct definitions (1)Luc Van Oostenryck2-7/+7
Type attributes for struct can be placed either just after the keyword 'struct' or after the '}' ending its definition but this later case is currently ignored. Prepare the handling of this by factoring the code common to both cases in a single place. Signed-off-by: Luc Van Oostenryck <luc.vanoostenryck@gmail.com>
2020-12-29apply_ctype: move up its declarationLuc Van Oostenryck1-2/+2
apply_ctype() will be needed earlier in the code. So, move it's prototype up. Signed-off-by: Luc Van Oostenryck <luc.vanoostenryck@gmail.com>
2020-12-29apply_ctype: reverse the order of argumentsLuc Van Oostenryck1-4/+4
apply_ctype()'s argument order confuse me endlessly as I'm much more used to have the destination first and the source next (the so called 'assignment order' used for assignments but also in memcpy() and in many sparse or library functions). So, change the argument order of apply_ctype() to mimic the order of memcpy()/assignment, to hopefully reduce my confusion. Signed-off-by: Luc Van Oostenryck <luc.vanoostenryck@gmail.com>
2020-12-29apply_ctype: use self-explanatory argument nameLuc Van Oostenryck1-10/+10
apply_ctype() is used to copy/apply things like modifiers and address space from one type to another one. But the names used for the two types are: 'ctype' & 'thistype' which doesn't help at all to know which one is the 'source' type and which one is the 'destination' type. Change this by renaming these arguments to 'src' & 'dst'. Signed-off-by: Luc Van Oostenryck <luc.vanoostenryck@gmail.com>
2020-12-29add testcases for packed bitfieldsLuc Van Oostenryck6-0/+172
Currently, packed bitfields are not handled correctly. Add some testcases for them. Signed-off-by: Luc Van Oostenryck <luc.vanoostenryck@gmail.com>
2020-12-29add testcases for packed structuresLuc Van Oostenryck2-0/+57
Currently, packed structs are not handled correctly. Add some testcases for them. Signed-off-by: Luc Van Oostenryck <luc.vanoostenryck@gmail.com>
2020-12-29add testcases for type attributesLuc Van Oostenryck4-0/+91
Currently, type attributes are not handled correctly. Add some testcases for them. Signed-off-by: Luc Van Oostenryck <luc.vanoostenryck@gmail.com>
2020-12-29add testcases for enum attributesLuc Van Oostenryck1-0/+29
Signed-off-by: Luc Van Oostenryck <luc.vanoostenryck@gmail.com>
2020-12-29add testcases for exotic enum valuesLuc Van Oostenryck1-0/+28
There is more than one complexity in the evaluation of enums. Add a test for enums with 'exotic' values not covered in other tests. Signed-off-by: Luc Van Oostenryck <luc.vanoostenryck@gmail.com>