- Important information
- New features
- Known problems
- Program corrections
- User guide corrections
- Miscellaneous
- Release history
Important information
- IAR Embedded Workbench for Arm 9.30 uses an updated version of
arm_mve.h
.- The new version can be included from both C and C++ (the version used in 9.20 could only be included from C).
- The new version does not affect the status of IAR extensions (the version used in 9.20 always enabled IAR extensions).
-
The names of the built-in MVE intrinsics have been updated to match the new
arm_mve.h
. As long as your application only uses the publicly visible names (the ones defined inarm_mve.h
) nothing changes, but if you refer directly to the built-in intrinsic functions, you must adapt to the new names.
- Limitations of compiler support for Armv8.1-M
There are some limitations to the support for Armv8.1-M in this release, to be addressed in a future release:
- MVE: The Cortex-M vector extension can be utilized by means of intrinsic functions.
There is currently no support for auto-vectorization. The header filecannot be included from C++ code. Some optimizations of MVE code are missing, in particular when a VCMP instruction is followed by VPST they should be combined into a VPT instruction. - LOB: Limited matching of low-overhead loops.
A candidate loop must have a loop counter that is counted down by 1 until it reaches zero. The presence of an outer loop can lead to an inner loop not being matched. Other optimizations (most notably loop unrolling) can lead to a loop not being matched. - CMSE: The Armv8.1-M register FPCXT_NS is not restored by a non-secure entry function.
- _Float16: Some operations on _Float16 (such as plus and minus) are implemented by converting the input operands to float, using the corresponding instruction for float, and converting the result to _Float16.
- The conditional instructions from Armv8-A are not utilized (CSEL, CSET, CNEG).
- MVE: The Cortex-M vector extension can be utilized by means of intrinsic functions.
- Characteristics for the toolset in AARCH64 mode:
- The toolset, by default, supports generating code and data that is situated in one space that has a maximum size of 4 Gbytes. This is because static data will be accessed with an addressing mode that reaches +/- 4 Gbytes. Mechanisms exist to jump/call between such spaces.
- The produced code, by default, runs in execution state EL1.
Limitations:
- Big-endian code is not supported.
- Position-independent code is not supported.
- V8-A AARCH32 is not fully implemented. The 32-bit implementation is currently based on v7-A.
- Compiler MISRA C C:1998/C:2004 support is removed in version 9.10
The Compiler MISRA C is still available through the compiler command line but will be removed in a future release.
Refer to IAR C-STAT for full MISRA C support. - Changes in implementation of CMSIS intrinsics in version 8.20
The implementation of the CMSIS intrinsic interface is no longer based on IAR's intrinsics.h. As a consequence of that some intrinsics that was previously declared when the CMSIS header was included are no longer declared.
Examples of these intrinsics include __LDREX(), __STREX() and __enable_interrupt().
- Changed size of wchar_t in version 8.10 and later
Object files following the ARM ABI has a runtime attribute indicating the size of
wchar_t
.In EWARM version 7.80 and earlier, the size of
wchar_t
was 2 bytes wide and the runtime attribute was set accordingly.In EWARM version 8.10 and later,
wchar_t
is 4 bytes wide. -
If you have implemented the
time()
function, you must rename it into__time32()
. For more information see the Development guide. -
A special note on CMSIS integration:
If your application source code includes CMSIS header files explicitly, then you should not select Project>Options...>General Options>Library Configuration>Use CMSIS. Some of the Cortex-M application examples include CMSIS source files explicitly. Do not select the option Use CMSIS in these projects.
Deprecated features
-
--interwork
Future versions of the IAR C/C++ Compiler for ARM will assume
--interwork
when generating code for the ARMv4T architecture. There will be no option to generate non-interworking code for ARMv4T.
-
New features
-
New and updated support for GCC's "Extensions to the C Programming Language"
- Additional support for __builtin function calls. If supported by the target core, these calls result in code generation using native instructions; else, they are transformed into library function calls.
- The attribute visibility is now supported in C.
- Support for arithmetic on void and function pointers (requires IAR language extensions).
- The __attribute__((__packed__)) construct can now be placed at the end of enum declarations.
-
Support for additional GCC relaxations to ISO C
- In a function that has the return type void, a return statement can return a void expression. For example, return (void)expr; (requires IAR language extensions).
- The error Pe042 ("operand types are incompatible") is now a soft error in more language constructs. By reducing the severity of this error and the errors Pe144 and Pe513, an application can mix void * and function pointers.
-
Common Subexpression Elimination (CSE)
The Common Subexpression Elimination (CSE) implementation in the optimizer has been improved for code containing loops. This may give up to 6% faster execution time in the general case.
In the following example, "a + b * c" occurs multiple times and can be optimized by the CSE optimization. Due to a loop between two occurrences of "a + b * c", there was earlier a conflict between optimizing for common subexpressions and loops. This has now been resolved.int g; int foo(int a, int b, int c) { bar(a + b * c); while(...) { ... } return g - (a + b * c); }
-
Experimental support for Sys V shared objects
Shared objects is a new type of output from the linker. It allows creation of shared libraries that can be dynamically loaded by an application. Use of shared objects requires the use of a dynamic loader/linker or something that can act like a dynamic linker. A dynamic linker can load shared objects into available memory and resolve references to and from them. Dynamic linkers are typically part of an operating system.
See IAR C/C++ Development Guide for more information. An example can be found in arm\src\sharedobjects. -
Experimental support for SARIF output
The SARIF output format is supported by the compiler, linker, assembler and C-STAT command line tools.
Known problems
-
[EWARM-12792, TPB-3881] The compiler does not emit a warning for uninitialized variables in relation to structs. This is a known limitation of the uninitialized variable analysis.
-
[EWARM-12748, TPB-3876] Compiling extremely large and deep expressions can take much longer than expected, in particular on optimization levels Low and None.
Workaround: Break expressions that contain hundreds of operations into smaller parts and combine the results from the parts.
-
[EWARM-12565, TPB-3874] In some situations, the compiler might register a local temporary in the wrong scope, causing an internal error. This can occur in situations where aggregate initialization is performed on a class with an array field of aggregate type that is implicitly initialized, and the aggregate type contains dynamic initialization via—for example—a default member initializer.
Example:
struct S { S(int const & e); }; struct SubAggr { S flags{0}; }; struct AggrWithArray { SubAggr elems[1]; }; AggrWithArray arr{}; // Internal Error
Workaround: Prevent aggregate initialization by excluding braces at the initialization point, or by adding a user-provided constructor to the class with a default member initializer, or make sure that default member initializers are called by value.
-
[EWARM-12526, TPB-3870] A memory order dependency causes the compiler's register allocation to differ between Linux and Windows. The generated code will sometimes be different but both variants are functionally equivalent and correct,
Workaround: There is no known workaround
-
[EWARM-12489, TPB-3869] In C++ source code, if the first member of a class/struct is initialized by default and the member is of class/struct type with a defined destructor, the compiler might generate the internal error [symbol_lookup_M31: ... <mangled name of destructor> ... . For example, the following code would generate such an internal error:
struct A { A(); ~A() = default; // This is the destructor that the error message refers to }; struct B { A member1{}; // This is the initialization that triggers it A member2; }; void UseObject() { B(); }
Workaround: 1) Re-order the members so that the first one is not initialized by default.
2) Add a constructor that initializes the member instead: B() : member1() {} -
The compiler can generate incorrect debug information for a variable that is changed locally in an isolated part of the user application, if that part ends with an early return and if the variable is put in a different register in this part than in the rest of the application. The code snippet below can trigger the problem, so that the debug information will contain the wrong location for broken from line 14 and onward.
float g(void); void barrier(void); int f(int v2) { float broken = 0.0f; switch (v2) { case 0: broken = g(); barrier(); return 5; case 1: broken = g(); } if (broken > 0.0f) return 1; return 0; }
-
[EWARM-11959] The implementation of __iar_argc_argv included in the semihosting library uses IAR extensions to the semihosting interface.
Workaround: Contact IAR support to receive a source file that contains a replacement implementation of the __iar_argc_argv function.
See also EWARM-11958 -
[EWARM-11958] Enabling semihosting on the linker command line or in the Embedded Workbench IDE Project>Options dialog box does not add support for command line parameters.
Workaround: Add --keep __iar_argc_argv to the linker command line or as an extra linker option in the the Embedded Workbench IDE Project>Options dialog box.
See also EWARM-11959 -
[EWARM-11953, TPB-3795] A static_assert on an "==" comparison between two floating-point constants (a GCC and MSVC extension) incorrectly produces Error[Pe031]: expression must have integral type.
Workaround: Cast the result of the comparison to an integral type.
-
[EWARM-11455, TPB-3789] The compiler is sometimes too conservative and keeps temporary variables that could be removed. This can cause temporary variables to be used for copying, even when none is needed. The generated code is still correct, however not optimal.
Workaround: There is no known workaround for this problem.
-
[EWARM-11283] The GCC C extension __auto_type is not supported for variable-length arrays (VLA).
-
[EWARM-10949, TPB-3746] On optimization level High, the compiler can generate incorrect code for functions that contain local variables with static storage duration, if they call a small function in the same module that in turn can call a function declared as noreturn. In the triggering example below, an indeterminate value will be written to the variable idx at the end of the function.
int *f(int x); void __attribute__((noreturn)) fail(void); static inline void check(_Bool condition) { if (!condition) fail(); } void g(int a, int b) { static int idx = 0U; int* pA = f(idx); check(pA != 0); *pA = a; if (b != 0) ++idx; }
Workaround: Prevent inlining of small functions that contain calls to functions declared as noreturn. Either use the #pragma optimize=no_inline directive, turn off inlining for the entire module, or reduce the optimization level to Medium or lower.
-
[EWARM-10849, TPB-3738] #pragma data_alignment cannot be used to specify alignment on an anonymous structure or union.
Workaround: Use the _Alignas keyword on one of the members.
-
[EWARM-10377] When running, the compiler uses both a compiler and a linker license slot.
-
[EWARM-9298] In some cases, when using NEON intrinsics with vector parameters, the compiler might generate an internal error.
Workaround: If an internal error is caused by the usage of a Neon intrinsic, it can in some cases help to switch to an optimization level higher than None.
-
[EWARM-7572, EWARM-8763, TPB-3377] The compiler can be extremely slow when compiling code that contains structs with hundreds of fields.
Workaround: Avoid structs with many fields.
-
[EWARM-6667, TPB-3086] The compiler can cluster variables that are initialized by copy and zero-initialized variables with static storage duration. When the total size of the variables initialized by copy is small compared to the total size of the zero-initialized variables, and if compressed initializers are not used, this can create a significant size overhead.
Workaround: Specify use of compressed initializers in the linker configuration file or turn off static clustering on the module.
-
[EWARM-5239, EW25660] Passing a parameter of type va_list to a C++ function, where the caller is defined in one object file and the callee in another, will result in a linker error if one of the two objects is built with EWARM 7.20 (or newer) and the other is built with EWARM 7.10 (or older).
-
[EWARM-4824, EW24720] MISRA-C:2004 rule 9.1 will not find all used uninitialized local variables.
-
[TPB-3817] When writing to bitfields in a volatile context, the compiler emits a read and a write of the underlying storage unit. This happens even if the bitfield has the same size as the type, for example, int a_member:32.
Workaround: When using a bitfield that has the same size as the type, the bitfield size specifier could be removed. For example `int a_member:32` could be rewritten `int a_member`.
Program corrections
-
In EWARM 9.60.3
[EWARM-12822] The LDR pseudo-instruction LDR register,=expression that loads a register with any 32-bit or 64-bit expression
can in some cases load a 64-bit constant from an address that does not have 8-bytes alignment. -
In EWARM 9.60.3
[EWARM-12785, TPB-3878] On optimization level High, the compiler can generate incorrect code when a single field of a struct is accessed and modified via a pointer multiple times, at different loop nesting levels. The observed effect is that updates to the field made in the inner levels are lost. -
Compiler warning Pa149 regarding enum values not covered in a switch statement does not detect the issue if the enum is declared with a type alias. The following example does not generate a warning:
typedef enum E { E1, E2 } E_t; void foo() { E_t e; switch (e) { case E1: break; } }
-
[EWARM-12314, TPB-3862] In C++, explicitly casting an rvalue that is of non-trivial class type, and where the explicit cast does not match the cv qualifiers of the respective lvalue reference, can lead to an incorrect life time for the lvalue.
#include <string> std::string get_str() { return ""; } void foo() { const std::string &str = (std::string)(get_str()); // The life time for str is incorrectly determined and // its destructor is run immediately. }
This only occurs at optimization level None.
-
[EWARM-12113, TPB-3852] The #pragma inline directive is not propagated to inherited constructors and destructors.
-
Declaring or defining an identifier both static and __weak (an illegal combination) results in an internal error in the compiler. Note that the problem occurs also when the combination of keywords is created by the use of one keyword in a declaration and the other one in a definition. For example:
static void f(); __weak void f() {} // Tool internal error. ElfOutput::Write: No group signature symbol set
-
[EWARM-12021, TPB-3843] Using one of the GNU function attributes const or pure on a function with return type void does not result in a warning.
-
[EWARM-12016, TPB-3860] Compiling using the options -
mfc,discard_unused_publics, and -stack_protection can cause the compiler to incorrectly remove the _stack_chk_fail function because it is not referenced by the user code (unless it was defined with the root attribute). This leads to an internal error because the compiler will afterward, internally, add calls to the _stack_chk_fail function. -
[EWARM-11962, EWARM-12831, TPB-3832, TPB-3883] In rare cases, the compiler might get stuck in an infinite loop after optimizing the computation of a variable that is conditionally updated inside a loop, for example if an assignment is optimized away.
-
static_cast conversions can erroneously try to use a user-defined conversion function instead of downcasting. This can lead to incorrect code being generated.
For example:
struct V { template <typename T> operator T() { return {42}; } }; struct J : V {}; void f() { auto v = V{}; static_cast<J const&>(v); // Error, tries to use T() for conversion which leads to type mismatch }
-
Initializing a union with a designated initializer, where the designator refers to any field except the first one and the first field of the union is a bitfield, causes the compiler to generate an internal error. Example code that triggers the problem:
union U { unsigned char first : 2; unsigned char second : 4; }; union U u = { .second= 1 };
-
Declaring multiple overloads with the same type, where the only difference is one or more data type attributes, causes an internal error. This is due to data type attributes being omitted from the C++ name mangling.
Compiling this example results in Internal error: [CoreUtil/General]: OgModuleLabels – label _Z3fooRi already defined:
void foo(int &) {} void foo(int __packed &) {}
-
[TPB-3816]
Initializing an array of structs with a combination of array and structure designators, when the struct itself contains an anonymous structure, can make the compiler crash.
struct X { struct { int y1, y2; }; }; struct X X_arr[2] = { [0].y1 = 0, [0].y2 = 0, [1].y1 = 1, [1].y2 = 1 };
-
[TPB-3698]
The compiler enters an infinite loop when a code pattern similar to the one provided in the example below is given as input. The problem is triggered only on optimization level High.
The code pattern that triggers the problem is an if statement, followed by an infinite while statement using the same condition.
The condition must be an equality check with a constant value, for example, (globalCond==0) or any logical combination of equality comparison expressions, for example, (globalCond1==0 && globalCond2==1).
Other relational or equality operators, like <, >, <=, >=, and !=, do not trigger the problem.
This example triggers the problem:
int globalCond; int globalVar; int TPB_3698 ( ) { if(globalCond==0) { globalVar = 0; } while (globalCond==0); return 0; }
User guide corrections
- None.
Miscellaneous
-
Available workarounds for device erratas:
-
CVE-2024-0151
Security weakness in PCS (Procedure Call Standard) for CMSE (Cortex-M security extensions).
The weakness in the PCS is that the 32-bit AEABI specifies that it is the callers responsibility to extend small arguments to register width, and that it is the callees responsibility to extend small return values to register width for CMSE this is handled as follows:
- small arguments are extended in prolog of non-secure entry functions
- small return values are extended at call-site after return from non-secure call
"small" in this context are values of `char` or `short` type, or enum or wide-characters if they are represented in either 8 bits or 16 bits.
More information is available on developer.arm.com.
In EWARM 9.50.4 and later, the compiler avoids this vulnerability. -
CVE-2021-35465
A VLLDM instruction Security Vulnerability affects Arm Cortex-M33 r0p0 to r1p0, Arm Cortex-M35P r0, Arm Cortex-M55 r0p0 to r1p0, and Arm China STAR-MC1 (STAR SE configuration).
On these processors, any Armv8-M Secure software that uses FPU or Helium instructions and that calls Non-secure functions might be affected.
In EWARM 9.20.1 and later, the compiler avoids this vulnerability. The workaround is enabled by default, but can be disabled using the command line option --enable_hardware_workaround no-fix-cmse-cve-2021-35465. -
ARM Cortex-M3 errata 463764
Core might freeze forSLEEPONEXIT
single instructionISR
. More information is available on infocenter.arm.com.
Workaround generated for functions with attribute__irq
withiccarm --enable_hardware_workaround=arm463764
. Supported from EWARM 5.41. -
ARM Cortex-M3 errata 602117
LDRD
with base in list might result in incorrect base register when interrupted or faulted. From EWARM 5.20.3 the compiler/library avoids theLDRD
instruction with the base register in list. -
ARM Cortex-M3 errata 752419
ARM Cortex-M4 errata 752770
Interrupted loads toSP
can cause erroneous behaviour. From EWARM 6.21 the compiler/library does not generateLDR SP
instructions with writeback toRn
. Otherwise we allow the extra reads because the stack resides in RAM where multiple reads are acceptable. -
ARM Cortex-M4 errata 776924
VDIV or VSQRT instructions might not complete correctly when very short ISRs are used. IAR recommends the second workaround proposed by Arm: "Ensure that every interrupt service routine contains more than 2 instructions in addition to the exception return instruction." The background is that the compiler is unaware of interrupts since the Cortex-M architecture does not distinguish between ordinary functions and interrupt functions. -
ARM Cortex-M7 errata 833872
Flag setting instructions inside an IT block might cause incorrect execution of subsequent instructions. From EWARM 7.40, the compiler will the skip the IT transformation on this particular code pattern. -
ARM Cortex-M3 errata 838469
ARM Cortex-M4 errata 838869
Store immediate overlapping exception return operation might vector to incorrect interrupt. Follow the guidelines in the errata and implement the workaround proposed by ARM by using__DSB(void)
in applicable cases. -
Functional problem Core.1 in NXP device LPC2478: Incorrect update of the Abort Link register in Thumb state.
Workaround generated withiccarm --enable_hardware_workaround=NXP_Core.1
-
Functional problem in Stellaris devices: Non-word-aligned write to SRAM can cause an incorrect value to be loaded. More information is available on the Stellaris web site at www.ti.com/stellaris.
Workaround generated withiccarm --enable_hardware_workaround=LM3S_NWA_SRAM_Write
-
Functional problem in Freescale Semiconductors MC9328MX1 (i.MX1), masks 0L44N, 1L44N, and 2L44N:
TheLDM
instruction will in some cases not load the second register correctly. Workaround generated withiccarm --enable_hardware_workaround=920t-ldm2
NOTE: The libraries in the current EWARM version are not built with this workaround. Use EWARM 6.50.6 and linker option--enable_hardware_workaround=920t-ldm2
to use libraries built with this hardware workaround.
-
-
RTOS Threads and TLS
The inc\c\DLib_Threads.h header file contains support for locks and thread-local storage (TLS) variables. This is useful for implementing thread support. For more information, see the header file.
-
va_args
The implementation of
va_args
functions has changed in IAR Embedded Workbench for ARM 7.20.1. It is no longer possible to compile the output of the preprocessor from an earlier version of the compiler. The original source code must be preprocessed again, using IAR Embedded Workbench for ARM 7.20.1.
Release history
-
See release history.