| CODEGEN-7011 |
Compiler intermittently fails with INTERNAL ERROR: opt2000 experienced a segmentation fault |
Fixed |
C2000_18.12.0.LTS |
C2000_18.12.5.LTS |
Compile at -o1 or less; the pass with the bug runs only at -o2 or greater. In this particular case, making m_register_address a regular field instead of a bitfield will also avoid the issue. There isn't a simple change to the source that might avoid it in the general case; avoidance requires that several aspects that combine for the error, don't combine. |
If a struct contains a bitfield, and a function contains both a read and a write of that bitfield, and the expression written includes an operation (such as '&' with a constant) that truncates the value in the same way that the bitfield write does, then the optimiser may crash due to a bad memory access.
The important detail is the write to the bitfield. Note that field writes in C++ don't look struct accesses, but are. Also note that the compiler can inline calls and rearrange code to create the problematic situation in ways that are not obvious. |
| CODEGEN-6911 |
Floating point comparison that fits min/max-index pattern can produce incorrect code |
Fixed |
C2000_18.12.0.LTS |
C2000_18.12.5.LTS |
Interpose some other statement that isn't a float-to-float assignment between the two float-to-float assignments under the IF. |
Code that looks like
if (A < B) {
B = A
X = Y
something_else()
}
where A, B, X, and Y are all float or double variables and the comparison is < or >, may execute the "something_else()" not only when A<B, but also when A==B, when compiled with optimisation.
The IF and the two assignments match the pattern for a C2000 intrinsic designed for the min-index and max-index operation -- finding not just the maximum or minimum value, but also its position in an array. The compiler will absorb them into the intrinsic call, but then mishandle the conditional for anything else in the IF block.
If the "something_else" part is empty -- the block contains only the two assignments -- then there won't be a problem. Otherwise, the assignments will happen only when A<B, but the "something_else" will happen when A<B or A==B. |
| CODEGEN-6682 |
Combination of many include paths and .cdecls causes assembler to segmentation fault |
Fixed |
C2000_18.12.0.LTS |
C2000_18.12.4.LTS |
Use no more than 99 total include paths plus .cdecls directives. |
Invoking the assembler with 100 or more combined --include options and .cdecls directives can cause it to crash. |
| CODEGEN-6666 |
64-bit to 32-bit assignment with predecrement causes compiler crash with INTERNAL ERROR: no match for ASG |
Fixed |
C2000_18.12.0.LTS |
C2000_18.12.5.LTS |
The problem is specific to a downcounting loop. If I replace the nearby "for" line with the commented-out up-counting version, there is no error. |
An assignment of a 64-bit value to a 32-bit-element array, inside a loop that counts down by 1, may cause the compiler to crash with an internal error message. |
| CODEGEN-6527 |
ELF-only $HI16 assembler relocation operator handled incorrectly, affecting _symval intrinsic |
Fixed |
C2000_18.12.0.LTS |
C2000_18.12.4.LTS |
Avoid using _symval and use HI16 instead of $HI16 |
The assembler will incorrectly accept the ELF-only relocation operators $HI16 and $LO16 in instructions that expect a 22-bit immediate or symbol, such as MOVL XARn, #22-bit. Further, the assembler will incorrectly emit a 22-bit R_REL22 relocation. In the case of $HI16, this means that the register will be loaded with an incorrect value. The compiler uses the $HI16 and $LO16 operators to implement the _symval() intrinsic. Any code which uses the _symval intrinsic, or uses the $HI16 operator in a 22-bit immediate context may have the incorrect relocation. |
| CODEGEN-6501 |
memory allocation functions do not robustly handle case of --heap_size=0 |
Fixed |
C2000_18.12.0.LTS |
C2000_18.12.4.LTS |
|
It is possible to set the size of the allocation heap to a total size (such as zero) that is too small to handle any allocations. The C library's dynamic memory allocation routines (e.g. malloc) did not gracefully handle allocations in this case. These functions might crash, or might scribble on unrelated program memory, or might return successfully with a bogus pointer, in which case the caller would likely proceed to write through the bogus pointer and scribble on arbitrary memory. |
| CODEGEN-6456 |
Under eabi, the cinit entry for zero fill an of uninitialized section has a length that is 1/2 of what it should be |
Fixed |
C2000_18.12.0.LTS |
C2000_18.12.4.LTS |
Initialise the problem variables to zero explicitly. |
Uninitialised variables in EABI mode are supposed to be implicitly initialised to zero. It is possible that C2000 programs will not fully initialise them; because of an error in converting from 16-bit bytes to 8-bit bytes, the size of the zero-initialised range (or ranges) may be only half the total size. |
| CODEGEN-6399 |
Compiler incorrectly optimizes volatile_long &= <constant> |
Fixed |
C2000_18.12.0.LTS |
C2000_18.12.3.LTS |
|
C2000 does not have 32-bit bitwise (AND, OR, XOR) instructions, so 32-bit bitwise operations must be done with two 16-bit bitwise instructions. This means that it is not possible to truly handle a 32-bit bitwise operation in an atomic manner, so it's not possible to satisfy the atomic requirement for bitwise operations on 32-bit volatile variables. In this case, the compiler is supposed to follow the rule that for a volatile read, the compiler will read every bit in the variable exactly once, and for every volatile write, the compiler will write every bit in the variable exactly once. This means there are only two valid instruction sequences: either two bitwise operations directly to memory, or a 32-bit load, followed by bitwise manipulation, followed by a 32-bit write. When generating the two 16-bit bitwise instructions, the compiler checked to see if any of the 16-bit bitwise instructions was a tautology, such as binary OR with an all-zero constant, in which case it dropped the tautological instruction. This is not legal if the instruction operated directly on volatile memory. The bug in this case is that the compiler did it anyway. |
| CODEGEN-6289 |
Pointer to VLA 2D array computation in IF condition is double-adjusted and garbled |
Fixed |
C2000_18.12.0.LTS |
C2000_18.12.3.LTS |
Given "if (p[i][j])", moving the access into a temp with "T = p[i][j]; if (T)" is the simplest workaround. Since the bug happens early in compilation, optimisation level doesn't matter.
Recasting the IF as a quest/colon, if feasible, is also a workaround. |
A variable-length-array access for an array of at least two dimensions, if used in the predicate of an IF statement, may be mishandled and refer to an incorrect element, possibly outside the array. |
| CODEGEN-6276 |
--opt_level=4, plus library compiled with 6.2.x or older, can cause no-match-for-UMULT error |
Fixed |
C2000_18.12.0.LTS |
C2000_18.12.3.LTS |
Make sure all code, even libraries, are compiled with 6.4.x or a later compiler version, or avoid using --opt_level=4. |
The C2000 compiler changed its internal representation of pointers from 22 bits to 32 bits around version 6.4.0. When encountering 22-bit pointer types, these recent compilers silently convert them to 32-bit types, and everything is usually fine.
The problem here is with a qualified pointer type -- "float * volatile" -- where the pointer type itself is qualified, not the type pointed to. Qualified 22-bit pointer types are not properly converted to 32 bits.
Normally that's no problem, because recent compilers will not produce 22-bit pointer types to worry about. However, libraries may have compiler internal representations embedded within them, for use when compiling with --opt_level=4. If the library is old enough, it may have been compiled with a pre-6.4.x compiler and thus have 22-bit pointers. At the .obj level, those aren't visible, but --opt_level=4 uses the embedded internal representation and then they're apparent.
This problem requires all these elements:
1. Library compiled with compiler older than 6.4.0.
2. Library contains embedded internal representation.
3. Library uses qualified pointers, eg, "float * volatile" or "int * const".
4. Project is compiled with --opt_level=4.
5. Project compiler is 18.1.x or newer.
The troublesome library in this case is SFRA_IQ_Lib.lib, which was compiled with version 6.2.8. |
| CODEGEN-6240 |
Should allow interlinking files with no CLA code and no CPU code |
Fixed |
C2000_18.12.0.LTS |
C2000_18.12.3.LTS |
Add a dummy function to your CLA data file to change it to a CLA object file with CLA instructions. |
The linker has a feature that allows object files composed only of CLA instructions to freely interlink with object files that have no CLA code, regardless of whether or not they use FPU32, TMU, or VCU (ref. SDSCM00052139). However, the intent was to also allow CLA object files that had no code whatsoever to freely interlink in the same way; this support was overlooked. |
| CODEGEN-6132 |
pdd tool fails when program includes unused file |
Fixed |
C2000_18.12.0.LTS |
C2000_18.12.3.LTS |
Leaving the sys_pcr.obj file out of the link command works, but it's hard to tell that that's the problem file. |
The profile decoder, armpdd or pdd2000 or pdd430 or pdd6x, may fail when the program on which it is called includes a file whose functions are not included in the link.
In the test case given, the file sys_pcr.obj contains functions that are not called anywhere and therefore are not included in the .out file. However, due to some quirk that we have not yet isolated, the debug info for sys_pcr.obj *is* included. When the profile decoder collects its data, it uses the debug info to locate it; the faulty extra debug info points to invalid locations, causing the warnings.
We don't know yet whether the problem is with a single excluded function, more than one, or a whole file whose functions aren't included. What we have done is to make the profile decoder recognise and ignore the bogus debug info. |
| CODEGEN-6131 |
C28 fast int div: FPU load scheduling issue |
Fixed |
C2000_18.12.0.LTS |
C2000_18.12.2.LTS |
Either disable fast integer division --idiv_support=none, or if using fast integer division, --idiv_support=idiv0, avoid using the specific case for the I64/UI64 fast integer division. |
For the C2000 fast integer division feature, --idiv_support=idiv0, FPU register loads could incorrectly move ahead of the ABSxxDIVxx instruction in a fast integer division sequence.
This could only happen for the I64/UI64 fast integer division case. |
| CODEGEN-6020 |
C28 fast int div: reduce unnecessary CPU to FPU MOVs |
Fixed |
C2000_18.12.0.LTS |
C2000_18.12.2.LTS |
Higher optimization levels, --opt_level=2 or greater, helped to offset this issue. |
For fast integer division feature, --idiv_support=idiv0, cases involving I64, UI64, I16 and UI16 were loading integer values to FPU registers by first loading to CPU registers, followed by the CPU-to-FPU register moves which add extra delay slots. |
| CODEGEN-6004 |
OFD erroneously prints 0x<decimal> where hex was intended |
Fixed |
C2000_18.12.0.LTS |
C2000_18.12.2.LTS |
Update the OFD binary |
When using OFD to view the DWARF debug information in an object file, OFD will incorrectly format what should be a hexadecimal number as 0x followed by the decimal value. This affects two contexts: When printing the FORM_ref4 offset of an attribute (such as DW_AT_type) DIE appearing in the same .debug_info section, and when printing the CIE ID. |
| CODEGEN-5943 |
Compiler may lose volatile qualifier in A->B->C when B and C are both volatile |
Fixed |
C2000_18.12.0.LTS |
C2000_18.12.2.LTS |
The expression has to contain both dereferences, eg, a->b->c, for the problem to appear. If they're separated by using a temp, as in
T * volatile p;
p = a->b;
... p->c ...
then the problem should be avoided. Making the temp "p" volatile is also important, to prevent the compiler from recombining the two dereferences.
Or compile with -o1, -o0, or -ooff. |
In an expression like A->B->C, when B and C are both volatile structure fields, we'd expect to see two distinct memory accesses every time. There is a bug in the compiler specifically with having two dereferences in a single expression, ie, A->B->C, in which it may lose the volatile qualifier from B. That may lead it to save A->B in a temporary variable and reuse that value instead of re-reading it as is supposed to happen. |
| CODEGEN-5905 |
Linker command file option --define with pathname with many directory components leads to error: "source line too long" |
Fixed |
C2000_18.12.0.LTS |
C2000_18.12.2.LTS |
|
|
| CODEGEN-5862 |
C2000 intrinsic __rpt_mov_imm fails to compile with negative source literal |
Fixed |
C2000_18.12.0.LTS |
C2000_18.12.2.LTS |
N/A |
When the C2000 intrinsic __rpt_mov_imm is used with a negative source operand, the compiler fails with a match error. This is because it was erroneously modeled as having an unsigned source operand. |
| CODEGEN-5843 |
Use of --check_misra=14.10 causes non-MISRA related warning to be emitted |
Fixed |
C2000_18.12.0.LTS |
C2000_18.12.3.LTS |
No direct workaround. The warning can be suppressed by the usual methods, or corrected as described in the report. |
If a local variable's address is taken before the variable is initialised, there will usually not be a warning with default settings. However, if any --check_misra option is used, the compiler will issue a used-before-set warning for the variable. |
| CODEGEN-5791 |
C++ enum class with explicit type has some problems |
Fixed |
C2000_18.12.0.LTS |
C2000_18.12.2.LTS |
Avoid specifying an explicit base type for an enum. |
Values of a C++ enum class type with an explicit base type may not be cast properly to and from integral types. The exact conditions depend on undefined behavior, and thus are not 100% predictable; the known cases happen only on Windows, though the compiler uses the same codebase on all platforms. |
| CODEGEN-5773 |
--emit_references:file causes an internal error on Mac |
Fixed |
C2000_18.12.1.LTS |
C2000_18.12.1.LTS |
|
|
| CODEGEN-5708 |
Parser crashes when zero-initializing unused local variable |
Fixed |
C2000_18.12.0.LTS |
C2000_18.12.1.LTS |
Remove the unused variable. |
The parser will crash if the source code attempts to create a local class, struct, union, or array variable that is never used and is zero-initialized. A local variable is zero-initialized if it has a partially specified initializer expression or if it is a class which requires zero-initialization. |
| CODEGEN-5674 |
Under -o4, compiler may assume a global variable is constant, if it's only set in files containing inline asm() |
Fixed |
C2000_18.12.0.LTS |
C2000_18.12.3.LTS |
First, compiling with -o3 (or less) instead of -o4 will avoid the problem.
Second, making g_sys_opmode volatile does indeed work around the problem. Since the "volatile" qualifier tells the compiler that something is modifying the variable outside the compiler's view, that's exactly what is needed to keep it from being assumed constant.
Third, removing the asm() from main.c will work around the problem, by including main.c in the recompilation. I modified EINT/DINT and EALLOW/EDIS macros in F2806x_Device.h and two cpu.h files, making them use the intrinsics __enable_interrupts, __disable_interrupts, __eallow, and __edis. As it happens, __enable_interrupts and __disable_interrupts control both INTM and DBGM, while the macros control them individually, so this may not be a completely satisfactory solution. |
The immediate trigger for the bug is that main.c contains asm() statements. That's the only file that sets g_sys_opmode; other files only read it. The presence of asm() keeps the file out of the recompilation that -O4 does. The compiler, however, still thinks it has the whole program (or at least the important parts); since it doesn't see main.c, it doesn't see the writes, and concludes that g_sys_opmode is a constant 0. |
| CODEGEN-5623 |
Makefile dependence generation (--preproc_dependency) should quote spaces in filenames |
Fixed |
C2000_18.12.0.LTS |
C2000_18.12.2.LTS |
Rename the files so that they don't have spaces in the names. |
The parser generates makefile dependencies with the --preproc_dependency option. However, if any filename has a space in its name, the makefile dependencies will not be formatted in a way that can be parsed by make. |
| CODEGEN-5580 |
C28 tmu1 __relaxed_powf bug |
Fixed |
|
C2000_18.12.0.LTS |
Either use --fp_mode=strict or update include/math.h with below:
__inline float __relaxed_powf(float x, float y)
{
float log2ofx = __log2(x);
float log2ofxtimesy = log2ofx * y;
float exp2foflog2ofxtimesy = exp2f(log2ofxtimesy);
return log2ofxtimesy > 0 ? exp2foflog2ofxtimesy : 1.0f / exp2foflog2ofxtimesy;
} |
Using --tmu_support=tmu1 --fp_mode=relaxed, below math.h routine did not properly handle a negative result for log2(x):
__inline float __relaxed_powf(float x, float y)
{
float log2ofx = __log2(x);
float log2ofxtimesy = log2ofx * y;
return exp2f(log2ofxtimesy);
}
Updated routine that handles negative log2(x):
__inline float __relaxed_powf(float x, float y)
{
float log2ofx = __log2(x);
float log2ofxtimesy = log2ofx * y;
float exp2foflog2ofxtimesy = exp2f(log2ofxtimesy);
return log2ofxtimesy > 0 ? exp2foflog2ofxtimesy : 1.0f / exp2foflog2ofxtimesy;
}
|
| CODEGEN-5574 |
Loop controlled by unsigned char counter iterates more than 255 times |
Fixed |
C2000_18.12.0.LTS |
C2000_18.12.2.LTS |
Compile at -o1 or less, or restructure the loop to make it not need the 8-bit wraparound. |
A do-while loop with an unsigned loop variable narrower than int can miss one of its wraparound cases, for instance if the loop counts down and the counter starts at zero. The compiler may promote the variable to int, making it wider than the original and thus it will experience a much larger count when it wraps. |
| CODEGEN-5563 |
Checking for MISRA rule 20.1 causes macro redefinition to be ignored |
Fixed |
C2000_18.12.0.LTS |
C2000_18.12.3.LTS |
None. To detect redefined macros that aren't predefined, --check_misra=20.1 must not be in the compilation options. |
The --check_misra=20.1 option, which looks for redefined reserved identifiers such as predefined macros, will accidentally suppress warnings about redefinitions of macros that *aren't* predefined. Since those aren't included in the group that 20.1 tests for, no warning will be issued at all. |
| CODEGEN-5551 |
C2000 ALT Guide lists incorrect processor symbolic constants |
Fixed |
C2000_18.12.0.LTS |
C2000_18.12.0.LTS |
|
The following processor constants listed in table 4.7.6 "Predefined Symbolic Constants" in the C2000 Assembly Language Tools user's guide don't exist:
TMS320C2800_CLA
TMS320C2800_TMU
Each of the available CLA, TMU and VCU processor constants is set to 1 if that value or greater of the device option is used.
|
| CODEGEN-5533 |
Loop with Cortex-R, -mf3, and DWARF debug leads to assembler error "defined differently in each pass" |
Fixed |
C2000_18.12.0.LTS |
C2000_18.12.3.LTS |
Several pieces have to come together for this problem to happen.
--opt_for_speed needs to be 3 or greater; thus a workaround is to reduce optimization to --opt_for_speed=1.
The source code has to have one or more IFs, followed by a nested scope that isn't part of a compound statement and defines local variables, followed by a loop. Another workaround is thus to move the local variable definitions to the enclosing scope. (Another that works for the given test case but isn't necessarily general is to initialise all those local variables, where they're defined in the nested scope.)
Normal debug info must be present; a final workaround is therefore to use --symdebug:none to suppress debug info. Of course, that makes debugging difficult. |
The assembler will become confused when presented with the sequence of a .align, an instruction that is smaller than the specified alignment, a label, and the DWARF DW_AT_low_pc directive. Because of the way it processes alignments and labels in different passes, it will conclude that the label was defined with two different values, and report an error.
This sequence is not something a human asm programmer would write. It arises from compiling a particular shape of statements in a loop, with a particular set of compilation options, to position the label and the .align and the directive. See the Workaround, which also indicates how to modify the code or compiler options to avoid this bug. |
| CODEGEN-5527 |
Local structure initialization is incorrectly optimized away |
Fixed |
C2000_18.12.0.LTS |
C2000_18.12.2.LTS |
None better than the one given in the description. |
A program that saves the address of a variable in an initialised local struct, but does not use the variable directly, may lose the part of the struct that saves the address. |
| CODEGEN-5511 |
Compilers other than C6000 mistakenly support option --legacy |
Fixed |
C2000_18.12.0.LTS |
C2000_18.12.2.LTS |
|
|
| CODEGEN-5460 |
Matching failure for intrinsic __euclidean_div_i32byu32 |
Fixed |
|
C2000_18.12.0.LTS |
Use intrinsics __rpt_subcul and __subcul |
When using the intrinsic __euclidean_div_i32byu32, the compiler will fail with an error similar to "no match for COMMA" |
| CODEGEN-5403 |
Improve documentation in Compiler Guides for PERSISTENT and NOINIT pragmas |
Fixed |
|
C2000_18.12.0.LTS |
|
|
| CODEGEN-5387 |
Loop with early exit may peel incorrectly when unrolling (as with -mf3 or above) |
Fixed |
|
C2000_18.12.0.LTS |
Add "#pragma UNROLL(1)" to the affected loop to inhibit unrolling, or compile with --opt_for_speed=2 or lower which inhibits unrolling of all loops. |
The compiler may unroll loops to speed them up. If it doesn't know the exact trip count, it needs to "peel" some iterations to make sure it does the extras if they don't fit exactly into the unrolled loop.
If the loop has an early exit -- in this case, it looks roughly like
while (flen-- && isdigit(*s)) ...
-- then there's a problem, because when the unrolled loop finishes, it could be because it's done, or it could be because isdigit(*s) returned false. If the unrolled part is done, we need to do the peeled part, but if isdigit() returned false, we don't, and the logic isn't ready for that conundrum and does the wrong thing. |
| CODEGEN-5317 |
Ternary (?:) expression with 0/1 result uses type of predicate, not result, when optimised |
Fixed |
|
C2000_18.12.0.LTS |
Compile with -Ooff. |
An expression like "(p ? 1 : 0)" can be converted by the compiler into "(p != 0)". If the types of 1 and 0 are wider than int, and the expression is shifted left, as in "(p ? 1UL : 0UL) << 16", then the value shifted will be int instead of the wider type, and the overall value will be incorrect. |
| CODEGEN-5305 |
Manual incorrectly states .bss, and not .data, is initialized by .cinit |
Fixed |
|
C2000_18.12.0.LTS |
|
|
| CODEGEN-5187 |
Compiler mishandles signed right-shifts by 16 on targets with 16-bit ints |
Fixed |
C2000_18.12.0.LTS |
C2000_18.12.0.LTS |
None known. |
For MSP430 and C2000, a right-shift of a signed long (ie, 32-bit) expression by 16 -- X>>16 -- will be compiled as an unsigned right-shift, which can lead to incorrect sign-extensions in the result. |
| CODEGEN-5119 |
Using #pragma RETAIN does not keep a static file level variable |
Fixed |
C2000_18.12.0.LTS |
C2000_18.12.2.LTS |
Use both "#pragma RETAIN" and "__attribute__((used))" at the same time. |
The RETAIN pragma may not keep an unused variable like it's supposed to. |
| CODEGEN-5032 |
Loop over array, preceded by shuffle of the array using scalar temp repeatedly, may produce incorrect results |
Fixed |
|
C2000_18.12.0.LTS |
The test case uses the same temp, nTemp, repeatedly in the shuffle function. Using different temps for each assignment will avoid the problem. Using "#pragma UNROLL(1)" to inhibit unrolling of the affected loops may also avoid the problem. |
The problem case looks something like
x = a[0]
a[1] = x
x = a[2]
a[3] = x
for (i = 0; i < N; i++) {
a[i] = ...
... a[i] ...
}
It shuffles data in an array a[] using the scalar x, then loops over array a[]. This particular arrangement, with the right optimisations, will do the wrong thing with the shuffle code. The wrong thing is part of optimising the loop, so both parts are required for there to be a problem. A workaround is to use a separate scalar variable for each assignment in the shuffle, ie, "x1 = a[0]; a[1] = x1" and "x2 = a[2]; a[3] = x2". |
| CODEGEN-4931 |
Applying __attribute__((used)) to static variable does not work |
Fixed |
C2000_18.12.0.LTS |
C2000_18.12.2.LTS |
|
|
| CODEGEN-4885 |
See MISRA diagnostics when compiling stdio.h |
Fixed |
C2000_18.12.0.LTS |
C2000_18.12.0.LTS |
none |
A program that includes <stdio.h> and checks for MISRA warnings may see some from stdio.h itself, which should not happen. |
| CODEGEN-4493 |
C2000 RTS should not force-inline sinf/cosf helper functions |
Fixed |
C2000_18.12.0.LTS |
C2000_18.12.2.LTS |
|
|
| SDSCM00050131 |
Local struct with non-constant initializer treated as static scope variable |
Fixed |
C2000_18.12.0.LTS |
C2000_18.12.1.LTS |
Completely specify every aggregate member in the initializer, or do not provide an initializer at all and instead populate each field with a statement. |
Function local non-static aggregate (array or struct) variables which are initialized to zero, or with an initializer that incompletely specifies all of the aggregate members, will be converted to static scope (global) objects. This is wrong; each time the function is entered, there should be a fresh copy of the variable. |