This is an archive of the discontinued LLVM Phabricator instance.

[MSP430] Update register names
ClosedPublic

Authored by atrosinenko on Jun 19 2020, 6:57 AM.

Details

Summary

When writing a unit test on replacing standard epilogue sequences with BR __mspabi_func_epilog_<N>, by manually asm-clobbering rN - r10 for N = 4..10, everything worked well except for seeming inability to clobber r4.

The problem was that MSP430 code generator of LLVM used an obsolete name FP for that register. Things were worse because when llc read an unknown register name, it silently ignored it.

Example: take the following source:

test-regs.c
void f(void)
{
  asm volatile ("" : : : "r0");
  asm volatile ("" : : : "r1");
  asm volatile ("" : : : "r2");
  asm volatile ("" : : : "r3");
  asm volatile ("" : : : "r4");
  asm volatile ("" : : : "r5");
}

void g(void)
{
  asm volatile ("" : : : "pc");
  asm volatile ("" : : : "sp");
  asm volatile ("" : : : "sr");
  asm volatile ("" : : : "cg");
  asm volatile ("" : : : "fp");
  asm volatile ("" : : : "r5");
}

and execute:

$ $sysroot/bin/msp430-elf-gcc --version
msp430-elf-gcc (Mitto Systems Limited - msp430-gcc 8.3.1.25) 8.3.1
Copyright (C) 2018 Free Software Foundation, Inc.
This is free software; see the source for copying conditions.  There is NO
warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.

$ $sysroot/bin/msp430-elf-gcc -c test-regs.c
test-regs.c: In function 'g':
test-regs.c:14:3: error: unknown register name 'pc' in 'asm'
   asm volatile ("" : : : "pc");
   ^~~
test-regs.c:15:3: error: unknown register name 'sp' in 'asm'
   asm volatile ("" : : : "sp");
   ^~~
test-regs.c:16:3: error: unknown register name 'sr' in 'asm'
   asm volatile ("" : : : "sr");
   ^~~
test-regs.c:17:3: error: unknown register name 'cg' in 'asm'
   asm volatile ("" : : : "cg");
   ^~~
test-regs.c:18:3: error: unknown register name 'fp' in 'asm'
   asm volatile ("" : : : "fp");
   ^~~
$ clang --version
clang version 10.0.0-4ubuntu1 
Target: x86_64-pc-linux-gnu
Thread model: posix
InstalledDir: /usr/bin
$ clang -target msp430 -c test-regs.c 
test-regs.c:14:26: error: unknown register name 'pc' in asm
  asm volatile ("" : : : "pc");
                         ^
test-regs.c:15:26: error: unknown register name 'sp' in asm
  asm volatile ("" : : : "sp");
                         ^
test-regs.c:16:26: error: unknown register name 'sr' in asm
  asm volatile ("" : : : "sr");
                         ^
test-regs.c:17:26: error: unknown register name 'cg' in asm
  asm volatile ("" : : : "cg");
                         ^
test-regs.c:18:26: error: unknown register name 'fp' in asm
  asm volatile ("" : : : "fp");
                         ^
5 errors generated.

No differences at all. Now, let's drop g() function, to make it valid source.

$ clang -target msp430 test-regs.c -S -emit-llvm -o-
...
; Function Attrs: noinline nounwind optnone
define dso_local void @f() #0 {
  call void asm sideeffect "", "~{r0}"() #1, !srcloc !2
  call void asm sideeffect "", "~{r1}"() #1, !srcloc !3
  call void asm sideeffect "", "~{r2}"() #1, !srcloc !4
  call void asm sideeffect "", "~{r3}"() #1, !srcloc !5
  call void asm sideeffect "", "~{r4}"() #1, !srcloc !6
  call void asm sideeffect "", "~{r5}"() #1, !srcloc !7
  ret void
}
...

Everything looks good, again.

$ clang -target msp430 test-regs.c -S -mllvm -stop-after=finalize-isel -o-
...
body:             |
  bb.0 (%ir-block.0):
    INLINEASM &"", 1, !2
    INLINEASM &"", 1, !3
    INLINEASM &"", 1, !4
    INLINEASM &"", 1, !5
    INLINEASM &"", 1, !6
    INLINEASM &"", 1, 12, implicit-def early-clobber $r5, !7
    RET

That is, I cannot use fp register name from the C code because Clang does not accept it (exactly like GCC). But the accepted name r4 is not recognised by llc (it can be used in listings passed to llvm-mc and even fp is replace to r4 by llvm-mc). So I can specify any of fp or r4 for the string literal of asm(...) but nothing in the clobber list.

This patch replaces MSP430::FP with MSP430::R4 in the backend code (even MSP430 EABI doesn't mention FP as a register name). The R0 - R3 registers, on the other hand, are left as is in the backend code (after all, they have some special meaning on the ISA level). It is just ensured clang is renaming them as expected by the downstream tools. There is probably not much sense in marking them clobbered but rename them just in case for use at potentially different contexts.

Diff Detail

Event Timeline

atrosinenko created this revision.Jun 19 2020, 6:57 AM
Herald added projects: Restricted Project, Restricted Project. · View Herald TranscriptJun 19 2020, 6:57 AM
Herald added a subscriber: hiraditya. · View Herald Transcript
atrosinenko edited the summary of this revision. (Show Details)Jun 19 2020, 6:59 AM
asl accepted this revision.Jun 22 2020, 2:41 AM

Looks good to me! FP was an old register name from mspgcc time. MSP430 EABI does not use frame pointer at all (seems to be a bug in the ABI, as I do not understand how we could support VLAs or alloca's in this case).

This revision is now accepted and ready to land.Jun 22 2020, 2:41 AM
This revision was automatically updated to reflect the committed changes.
atrosinenko reopened this revision.Jun 22 2020, 5:41 AM
This revision is now accepted and ready to land.Jun 22 2020, 5:41 AM

Fix compile error when building with older compilers.

This revision was automatically updated to reflect the committed changes.