This is an archive of the discontinued LLVM Phabricator instance.

[CodeGen] emit inline asm clobber list warnings for reserved
ClosedPublic

Authored by stuij on Jul 24 2018, 5:49 AM.

Details

Summary

Currently, in line with GCC, when specifying reserved registers like sp or pc on an inline asm() clobber list, we don't always preserve the original value across the statement. And in general, overwriting reserved registers can have surprising results.

For example:

extern int bar(int[]);

int foo(int i) {
  int a[i]; // VLA
  asm volatile(
      "mov r7, #1"
    :
    :
    : "r7"
  );

  return 1 + bar(a);
}

Compiled for thumb, this gives:

$ clang --target=arm-arm-none-eabi -march=armv7a -c test.c -o - -S -O1 -mthumb
...
foo:
        .fnstart
@ %bb.0:                                @ %entry
        .save   {r4, r5, r6, r7, lr}
        push    {r4, r5, r6, r7, lr}
        .setfp  r7, sp, #12
        add     r7, sp, #12
        .pad    #4
        sub     sp, #4
        movs    r1, #7
        add.w   r0, r1, r0, lsl #2
        bic     r0, r0, #7
        sub.w   r0, sp, r0
        mov     sp, r0
        @APP
        mov.w   r7, #1
        @NO_APP
        bl      bar
        adds    r0, #1
        sub.w   r4, r7, #12
        mov     sp, r4
        pop     {r4, r5, r6, r7, pc}
...

r7 is used as the frame pointer for thumb targets, and this function needs to restore the SP from the FP because of the variable-length stack allocation a. r7 is clobbered by the inline assembly (and r7 is included in the clobber list), but LLVM does not preserve the value of the frame pointer across the assembly block.

This type of behavior is similar to GCC's and has been discussed on the bugtracker: https://gcc.gnu.org/bugzilla/show_bug.cgi?id=11807 . No consensus seemed to have been reached on the way forward. Clang behavior has briefly been discussed on the CFE mailing (starting here: http://lists.llvm.org/pipermail/cfe-dev/2018-July/058392.html). I've opted for following Eli Friedman's advice to print warnings when there are reserved registers on the clobber list so as not to diverge from GCC behavior for now.

The patch uses MachineRegisterInfo's target-specific knowledge of reserved registers, just before we convert the inline asm string in the AsmPrinter.

If we find a reserved register, we print a warning:

repro.c:6:7: warning: inline asm clobber list contains reserved registers: R7 [-Winline-asm]
      "mov r7, #1"
      ^

Diff Detail

Event Timeline

stuij created this revision.Jul 24 2018, 5:49 AM
stuij edited the summary of this revision. (Show Details)Jul 24 2018, 5:58 AM

This is a good idea.

Can you add a note to the diagnostic explaining why this is a problem?

Please add a testcase for clobbering the base pointer in a function with a VLA.

stuij updated this revision to Diff 157486.Jul 26 2018, 8:09 AM

Added an explanatory note to the warning, and added a VLA testcase.

efriedma added inline comments.Jul 27 2018, 5:04 PM
lib/CodeGen/AsmPrinter/AsmPrinterInlineAsm.cpp
564

I'm not sure what "may not be preserved across function calls" has to do with this warning. And I'd prefer "undefined behavior" rather than "unexpected results".

stuij updated this revision to Diff 157932.Jul 30 2018, 2:37 AM

updated warning message

stuij added inline comments.Jul 30 2018, 7:25 AM
lib/CodeGen/AsmPrinter/AsmPrinterInlineAsm.cpp
564

Ah thanks, "across function calls" was a logical typo. That should read "across the asm statement".

efriedma added inline comments.Aug 6 2018, 5:32 PM
lib/CodeGen/AsmPrinter/AsmPrinterInlineAsm.cpp
556

Standard style is std::string Msg = "...";.

566

Doesn't the note need the same location to print correctly?

stuij added inline comments.Aug 7 2018, 9:59 AM
lib/CodeGen/AsmPrinter/AsmPrinterInlineAsm.cpp
566

With a clean SMLoc, the note doesn't contain line info. I thought that was cleaner than adding line info. This way it's more obvious on sight that the note is explaining something about the warning.

But thinking about it a bit more, it is a bit idiosyncratic. Changed to regular behavior in this patch.

stuij updated this revision to Diff 159534.Aug 7 2018, 10:02 AM

Follow LLVM style.

This revision is now accepted and ready to land.Aug 7 2018, 11:16 AM
This revision was automatically updated to reflect the committed changes.