Skip to content

NEW TOOLCHAIN: Add the ARMC6 compiler #4905

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Closed
wants to merge 4 commits into from

Conversation

theotherjimmy
Copy link
Contributor

@theotherjimmy theotherjimmy commented Aug 14, 2017

Description

This PR adds a new compiler to mbed OS: ARM Compiler 6 or armclang. This compiler
uses LLVM and CLang as the front end to an ARM proprietary optimization and code
generation layer. ARMC6 supports the new ARMv8M, ARMv8R and ARMv8A architectures.

Design notes

You may notice, when reviewing the code, that the ARMC6 toolchain class does not
inherit from the ARM toolchain class. This is intentional. While ARMC6 does use
the same linker (armlink) and assembler (armasm) as ARM Compiler 5, it is not
compatible.

The reason for this incompatibility are twofold:

  • armlink and armasm may invoke the C preprocessor by adding a shebang (#!) to
    the top of their input files.
  • ARMC6 and ARMC5 differ in how you invoke the preprocessor:
    • ARMC5: #! armcc -E
    • ARMC6: #! armclang -E

When a toolchain inherits from another, each of their class names become
converted a TOOLCHAIN_<name> define and the resource scanner will pick up
files within directories of the same name. If ARMC6 were to inherit from the
ARM base class, it would pick up the arm assembler and linker files, which
contain a possibly incorrect preprocessor invocation. The correctness of the
preprocesssor invocation depends on if you have ARM Compiler 5 installed. This
is generally a Bad Thing. Therefore, I elected to force the semi-duplication of
these files to guarantee that the invocation is correct for each toolchain.

I have made a new partial Toolchain implementation for ARMASM, and created
a pair of

Current limitations

Presently, the tools are not creating or processing dependency files for ARMC6.
This can make development with it a headache. I consider this an essential
feature of a toolchain and will be updating this PR to include it. Done.

Also, The output of ARMC6 is not filtered in any way to generate the short
version of each warning or error. This makes development with ARMC6 a little
verbose. I consider this a nonessential feature and will submit another PR to
include output processing unless someone convinces me otherwise.

Further, ARMC6 is not supported by the small build profile. This was an unintentional
omission, and I will correct it in this PR.
Done.

This PR only adds K64F support for ARMC6. I think that other devices should be
supported with subsequent PRs, so I'm not going to add support in this PR.

There is no exporter for Uvision + ARMC6. I think this is also out of scope and
should come as a separate PR.

TODO

  • Write section detailing this new toolchain in the Handbook
  • Add ARMC6 to the CI
  • Run nightly test to verify my implementation of ARMC6
  • Process dependency information for ARM6
  • Add small profile
  • Small error/warning messages

rtos/mbed_boot.c Outdated
@@ -232,7 +232,7 @@ osMutexAttr_t singleton_mutex_attr;
#if !defined(HEAP_START)
#if defined(__ICCARM__)
#error "Heap should already be defined for IAR"
#elif defined(__CC_ARM)
#elif defined(__CC_ARM) || defined (__ARMCC_VERSION) && (__ARMCC_VERSION >= 6010050)
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

You might consider wrapping defined (__ARMCC_VERSION) && (__ARMCC_VERSION >= 6010050) in parentheses as is done below.

@@ -400,7 +400,14 @@ void pre_main (void)
With the RTOS there is not only one stack above the heap, there are multiple
stacks and some of them are underneath the heap pointer.
*/
#if defined (__ARMCC_VERSION) && (__ARMCC_VERSION >= 6010050)
__asm(".global __use_two_region_memory\n\t");
__asm(".global __use_no_semihosting\n\t");
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Does the ARMCC reference manual recommend setting __use_two_region_memory and __use_no_semihosting using this syntax? Its a bit odd seeing inline assembly outside the body of a function.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@@ -595,7 +595,6 @@ void *__user_perthread_libspace (void) {
typedef void *mutex;

// Initialize mutex
__USED
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why was __USED removed for _mutex_initialize only and not the other functions like _mutex_free?

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think that has to be reverted, I remember linker was removing these symbols for some reason.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

When that was in, it was conflicting with our define. We should look into why Used + Weak was not working correctly.

Copy link
Contributor Author

@theotherjimmy theotherjimmy Aug 15, 2017

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

When I revert this change, I get the following linker error:

Error: L6200E: Symbol _mutex_initialize multiply defined (by rtx_lib.o and mbed_boot.o).

It looks like __USED beats __WEAK

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@0xc0170 I think you fixed issues with the tests with ops (malloc?) not being thread safe due to these symbols being stripped out?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Looking through CMSIS RTX 5 source, it looks like we added the weak.

@@ -58,7 +58,7 @@ void __assert_func(const char *file, int line, const char *func, const char *fai
void InstallIRQHandler(IRQn_Type irq, uint32_t irqHandler)
{
/* Addresses for VECTOR_TABLE and VECTOR_RAM come from the linker file */
#if defined(__CC_ARM)
#if defined(__CC_ARM) || defined (__ARMCC_VERSION) && (__ARMCC_VERSION >= 6010050)
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

parentheses

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Is there any way we can simplify this?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@bulislaw Not that I'm aware of

tools/memap.py Outdated
@@ -770,7 +770,7 @@ def parse(self, mapfile, toolchain):
self.list_dir_obj(os.path.abspath(mapfile))

if toolchain == "ARM" or toolchain == "ARM_STD" or\
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

nitpick - could you put this on one line with

if toolchain in ("ARM", "ARM_STD", "ARM_MICRO", "ARMC6"):

"ARMC6": {
"common": ["-c", "--target=arm-arm-none-eabi", "-mthumb", "-g", "-O0"],
"asm": [],
"c": ["-D__ASSERT_MSG", "-fno-rtti", "-std=gnu99"],
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Is -fno-rtti a valid C option? I thought rtti was only for C++ classes.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It does not seem to mind. I'll take it out

@@ -23,6 +23,13 @@
"cxx": ["--cpp", "--no_rtti", "--no_vla"],
"ld": []
},
"ARMC6": {
"common": ["-c", "--target=arm-arm-none-eabi", "-mthumb", "-g", "-O3", "-Os"],
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Is it valid to have both -O3 and -Os?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@0xc0170
Copy link
Contributor

0xc0170 commented Aug 15, 2017

👍 for the description, some of the info might be part of the commit message (I assume you will add more there once you rebase)

Add ARMC6 to the CI

@studavekar Please confirm as soon as ARMC6 is installed in our CI to test this PR (for those targets it supports at least , for now would be k64f)

@theotherjimmy
Copy link
Contributor Author

@0xc0170 Detailed design description added to first commit message. squashed fix commits into Enable K64F commit.

@theotherjimmy
Copy link
Contributor Author

@0xc0170 That second rebase was to re-flow the text of the commit message.

@theotherjimmy theotherjimmy force-pushed the feature-armc6 branch 4 times, most recently from f86bb08 to b25d713 Compare August 15, 2017 14:32
@theotherjimmy
Copy link
Contributor Author

@c1728p9 I rebased again to address all of the comments that I could right now.

@theotherjimmy
Copy link
Contributor Author

@c1728p9 Dependency parsing is up.

@theotherjimmy
Copy link
Contributor Author

Some numbers:

mbed-os-example-blinky# mbed compile -t armc6 -m k64f --profile develop
[SNIP]
+-------------------+-------+-------+------+
| Module            | .text | .data | .bss |
+-------------------+-------+-------+------+
| [lib]/c_wu.l      | 12539 |    16 |  348 |
| [lib]/fz_wm.l     |    18 |     0 |    0 |
| [lib]/m_wm.l      |    48 |     0 |    0 |
| anon$$obj.o       |    32 |     0 | 1024 |
| lto-llvm-8f8bc0.o | 16418 |   200 | 6972 |
| mbed-os/rtos      |   184 |     0 |    0 |
| mbed-os/targets   |  1488 |     0 |    0 |
| Subtotals         | 30727 |   216 | 8344 |
+-------------------+-------+-------+------+
Total Static RAM memory (data + bss): 8560 bytes
Total Flash memory (text + data): 30943 bytes
mbed-os-example-blinky# mbed compile -t armc6 -m k64f --profile release
+-------------------+-------+-------+------+
| Module            | .text | .data | .bss |
+-------------------+-------+-------+------+
| [lib]/c_wu.l      |  9674 |    16 |  348 |
| [lib]/fz_wm.l     |    14 |     0 |    0 |
| [lib]/m_wm.l      |    48 |     0 |    0 |
| anon$$obj.o       |    32 |     0 | 1024 |
| lto-llvm-aebb6c.o | 15265 |   200 | 6956 |
| mbed-os/rtos      |   184 |     0 |    0 |
| mbed-os/targets   |  1488 |     0 |    0 |
| Subtotals         | 26705 |   216 | 8328 |
+-------------------+-------+-------+------+
Total Static RAM memory (data + bss): 8544 bytes
Total Flash memory (text + data): 26921 bytes

@theotherjimmy
Copy link
Contributor Author

GCC for comparison

blinky# mbed compile -t gcc_arm -m k64f  --profile develop
+------------------+-------+-------+------+
| Module           | .text | .data | .bss |
+------------------+-------+-------+------+
| [fill]           |    62 |     4 | 2369 |
| [lib]/libc.a     | 22681 |  2472 |   56 |
| [lib]/libgcc.a   |  3090 |     0 |    0 |
| [lib]/libnosys.a |    32 |     0 |    0 |
| [lib]/misc       |   192 |     4 |   25 |
| main.o           |    56 |     0 |    4 |
| mbed-os/features |    42 |     0 |  184 |
| mbed-os/hal      |   570 |     0 |   24 |
| mbed-os/platform |  1226 |     4 |  270 |
| mbed-os/rtos     |  8439 |   180 | 5728 |
| mbed-os/targets  |  8027 |    12 |  384 |
| Subtotals        | 44417 |  2676 | 9044 |
+------------------+-------+-------+------+
Total Static RAM memory (data + bss): 11720 bytes
Total Flash memory (text + data): 47093 bytes
blinky# mbed compile -t gcc_arm -m k64f  --profile release
+------------------+-------+-------+------+
| Module           | .text | .data | .bss |
+------------------+-------+-------+------+
| [fill]           |    35 |     4 | 2217 |
| [lib]/libc.a     |  2456 |  2108 |   48 |
| [lib]/misc       |   192 |     4 |   25 |
| main.o           |    56 |     0 |    4 |
| mbed-os/features |    42 |     0 |  184 |
| mbed-os/hal      |   570 |     0 |   24 |
| mbed-os/platform |   720 |     4 |  270 |
| mbed-os/rtos     |  8439 |   180 | 5728 |
| mbed-os/targets  |  4930 |    12 |  384 |
| Subtotals        | 17440 |  2312 | 8884 |
+------------------+-------+-------+------+
Total Static RAM memory (data + bss): 11196 bytes
Total Flash memory (text + data): 19752 bytes

@MarceloSalazar
Copy link

This is a bit suspicious:
GCC (release), Flash = 19752 bytes
ARMC6 (release), Flash = 26921 bytes

Is the release profile optimizing for RAM at the expense of increasing Flash?

@theotherjimmy theotherjimmy force-pushed the feature-armc6 branch 3 times, most recently from 9a69359 to ab3cfac Compare August 17, 2017 18:09
@theotherjimmy
Copy link
Contributor Author

Alrightly, I rebased, squashing like changes, and splitting unlike changes. Should still build (I have a super cool CI like thing running in the background of my rebase) and the commit history should make more sense now.

@@ -595,7 +595,9 @@ void *__user_perthread_libspace (void) {
typedef void *mutex;

// Initialize mutex
#if !defined(__ARMCC_VERSION) || __ARMCC_VERSION < 6010050
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I've asked in ARM-software/CMSIS_5#213 (comment) whether CMSIS guys have some better way of doing that.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks @bulislaw. It looks like they're staying until the CMSIS guys can find a better solution.

@theotherjimmy
Copy link
Contributor Author

theotherjimmy commented Aug 18, 2017

FYI, another rebase coming. I'm going to try REPLACING ARMC5 with ARMC6. I think it will yield a much simpler implementation.

While ARMC6 does use the same linker (armlink) as ARM Compiler 5, it
is not compatible.

The reason for this incompatibility are twofold:
 * armlink may invoke the C preprocessor by adding a shebang
   (`#!`) to the top of their input files.
 * ARMC6 and ARMC5 differ in how you invoke the preprocessor:
   * ARMC5: `#! armcc -E`
   * ARMC6: `#! armclang -E`

This does not yet handle dependencies properly
@theotherjimmy
Copy link
Contributor Author

Closing this version of the PR, as the alternate implementation in #4949 Is better in most ways.

@theotherjimmy theotherjimmy deleted the feature-armc6 branch August 24, 2017 18:35
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

5 participants